SQL - 四表间查询

SQL - Query between four tables

我的查询有问题。

select  p.id, p.firstname, p.lastname , max(s.year) as 'Last Year', min(s.year) as 'First Year', c.name from pilot p
join country on country.sigla = p.country
join circuit c on c.country_id = country.sigla
join season s
on(p.id = s.pilot_id)
group by p.id, p.firstname, p.lastname, c.name
order by p.id

Table飞行员

Id (Primary Key)
Name
Table Season

Table 赛季

Year (Primary key)
Pilot_id (Foreign Key)

Table 国家

Sigla (Primary Key)

Table电路

id (Primary Key)
name

table Pilot 链接到季节和国家/地区。并且 table 电路链接到国家/地区。 我想为每个飞行员展示每条线路中的最后一个和第一个电路,但问题是我有重复的结果。第一个结果向我展示了第一个电路,而副本向我展示了最后一个电路。我有 67 个结果,我只想得到 40 个(数据库中的飞行员总数)

像这样使用内联 sql 根据您的表格编辑一个

SELECT *
FROM (
    SELECT p.id
        ,p.firstname
        ,p.lastname
        ,FirstCircuit = (
            SELECT TOP 1 circuitname
            FROM circuit c
            WHERE p.id = c.id
            ORDER BY year ASC
            )
        ,LastCircuit = (
            SELECT TOP 1 circuitname
            FROM circuit c
            WHERE p.id = c.id
            ORDER BY year DESC
            )
    FROM pilot p
    INNER JOIN country ON country.sigla = p.country
    INNER JOIN season s ON (p.id = s.pilot_id)
    ) tbl
GROUP BY id
    ,firstname
    ,lastname
ORDER BY id

借用上面的答案并进一步解释,因为我无法对此发表评论。 您需要为第一年和最后一年编写子查询,以便为每一年使用不同的 select 条件。对于第一年,您希望按 ASC 年排序以获得列中的最小年份。对于去年,您需要按年份 DESC 排序以获得列中最大的年份。

SELECT *
FROM (
    SELECT p.id
        ,p.firstname
        ,p.lastname
        ,FirstCircuit = (
            SELECT TOP 1 circuitname
            FROM circuit c
            WHERE p.id = c.id
            ORDER BY year ASC
            )
        ,LastCircuit = (
            SELECT TOP 1 circuitname
            FROM circuit c
            WHERE p.id = c.id
            ORDER BY year DESC
            )
    FROM pilot p
    INNER JOIN country ON country.sigla = p.country
    INNER JOIN season s ON (p.id = s.pilot_id)
    ) tbl
GROUP BY id
    ,firstname
    ,lastname
ORDER BY id

我怀疑问题出在 circuit table 的连接上。

无需替换 select 列表中的 MIN(s.year)MAX(s.year) 表达式。 (尽管有其他答案的建议,但这并不能解决真正的问题......每个飞行员仅获得 return 符合规范的 one 行。)

从一个更简单的查询开始调试...仅加入 pilot table 和 season table。例如:

 select p.id
      , p.firstname
      , p.lastname
      , max(s.year) as 'Last Year'
      , min(s.year) as 'First Year'
   from pilot p
   join season s
     on p.id = s.pilot_id
  group by p.id, p.firstname, p.lastname
  order by p.id

那应该 return,每个 pilot 最多一行(假定 idpilot table 中是唯一的。)由于内部联接,pilotseason 中没有任何关联的行将被排除。

当您将联接添加到其他 table(countrycircuit)时,您可能会引入重复行。但是这些行将 "collapsed" 变成每个飞行员的一行。

当您在 GROUP BY 中包含 c.name 时,您的 "duplicate" 行就会开始出现在您的结果集中。使用 GROUP BY 子句中的该表达式,您有可能为每个飞行员返回不止一行。

这就是问题所在。

您将保证每个飞行员的 returned 行具有不同的 c.name 值。

要解决此问题,您可以从 GROUP BY 子句中删除 c.name,并在 select 列表中使用聚合表达式,例如 MAX(c.name)

该查询 return(最多)每个飞行员一行。 (同样,如果 circuit 中没有行与与飞行员关联的 country 关联,则这些飞行员​​行将被排除。)

 select p.id
      , p.firstname
      , p.lastname
      , max(s.year) as 'Last Year'
      , min(s.year) as 'First Year'
      , max(c.name) as circuit_name
   from pilot p
   join season s
     on p.id = s.pilot_id
   join country 
     on country.sigla = p.country
   join circuit c
     on c.country_id = country.sigla
  group by p.id, p.firstname, p.lastname
  order by p.id

关于 return "first and last circuit on each line"...

你如何确定每个飞行员哪个电路是"first",哪个电路是"last"?我们在 table 中看到的仅有的两列是 idnamepilotcircuit 之间的唯一关系(显示)是通过 country table。一个 pilot 只有一个 country,因此导频与 country 中的每个电路相关联。