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
最多一行(假定 id
在 pilot
table 中是唯一的。)由于内部联接,pilot
在 season
中没有任何关联的行将被排除。
当您将联接添加到其他 table(country
和 circuit
)时,您可能会引入重复行。但是这些行将 "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 中看到的仅有的两列是 id
和 name
。 pilot
和 circuit
之间的唯一关系(显示)是通过 country
table。一个 pilot
只有一个 country
,因此导频与 country
中的每个电路相关联。
我的查询有问题。
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
最多一行(假定 id
在 pilot
table 中是唯一的。)由于内部联接,pilot
在 season
中没有任何关联的行将被排除。
当您将联接添加到其他 table(country
和 circuit
)时,您可能会引入重复行。但是这些行将 "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 中看到的仅有的两列是 id
和 name
。 pilot
和 circuit
之间的唯一关系(显示)是通过 country
table。一个 pilot
只有一个 country
,因此导频与 country
中的每个电路相关联。