以下查询完全按预期工作,并获得我想要的结果。
有没有更好的方法来写这个?问题是"打印所有团队ID,团队与费城人队对战,但不打击勇士队#34;这两个表的设置如下:
游戏:gameID,homeTeamID,guestTeamID,日期
队: teamID,teamName,home,leagueName
homeTeamID和guestTeamID是Teams表的外键,gameID和teamID都是主键。目前使用sql server dialect。
我真的觉得我是以一种荒谬的方式写这篇文章的,而且我必须做一些我不知道的事情。
WITH philliesgames AS
(
SELECT g.*
FROM games g
JOIN teams t
ON g.hometeamid = t.teamid
OR g.guestteamid = t.teamid
WHERE t.teamname = 'Phillies'), bravesgames AS
(
SELECT g.*
FROM games g
JOIN teams t
ON g.hometeamid = t.teamid
OR g.guestteamid = t.teamid
WHERE t.teamname = 'Braves')
(
SELECT guestteamid
FROM philliesgames
WHERE guestteamid <> 1
UNION
SELECT hometeamid
FROM philliesgames
WHERE hometeamid <> 1)
EXCEPT
(
SELECT guestteamid
FROM bravesgames
UNION
SELECT hometeamid
FROM bravesgames)
答案 0 :(得分:1)
试试这个:
select
IIF(t.teamid = g.hometeamid, g.guestteamid, g.hometeamid) id
from games g inner join teams t
on t.teamid in (g.hometeamid, g.guestteamid)
where t.teamname = 'Phillies'
except
select
IIF(t.teamid = g.hometeamid, g.guestteamid, g.hometeamid)
from games g inner join teams t
on t.teamid in (g.hometeamid, g.guestteamid)
where t.teamname = 'Braves';
如果您的SQL Server版本不支持IIF
,请改用CASE
:
IIF(t.teamid = g.hometeamid, g.guestteamid, g.hometeamid)
到
CASE t.teamid WHEN g.hometeamid THEN g.guestteamid ELSE g.hometeamid END
答案 1 :(得分:1)
这是另一种方法:
with teamGames(teamId, againstId) as (
select homeTeamId, guestTeamId from games
union
select guestTeamId, homeTeamId from games
)
select teamId
from teamGames
group by teamId
having
count(case when againstId =
(select teamId from Teams where teamName = 'Phillies')
then 1 end) >= 1
and count(case when againstId =
(select teamId from Teams where teamName = 'Braves')
then 1 end) = 0;
编辑:为了完整起见,我想回来添加一些笔记。
首先,我有点怀疑SQL Server会在having
子句中抱怨我的子查询,实际上它不允许这样做。我已经解决了以下问题。
with teamGames(teamId, againstId) as (
select homeTeamId, guestTeamId from games
union
select guestTeamId, homeTeamId from games
)
select g.teamId
from
teamGames as g
inner join teams as t1 on t1.teamId = g.teamId
inner join teams as t2 on t2.teamId = g.againstId
where t1.teamName not in ('Phillies', 'Braves')
group by g.teamId
having
count(case when t2.teamName = 'Phillies' then 1 end) >= 1
and count(case when t2.teamName = 'Braves' then 1 end) = 0;
我的查询版本具有巨大的优势,能够轻松添加任何数量的类似条件,而您的查询将变得更加复杂。将辅助数据添加到输出也更容易。但另外还有一点值得注意:您的union
和except
逻辑主要在关系中对称地对待每个团队。
在我的第二个查询中,我添加了一个检查,以防止Braves作为结果之一返回。勇敢者可以很好地发挥费城人队,而他们不可能自己发挥。根据您的定义,它们也可能是匹配的。只有隐含的常识,我们才假设勇士队不是你期望在结果中看到的团队。
您的查询必须处理费城人从未玩过勇士队的情况,否则不会被排除在名单之外。这似乎解释了<> 1
检查。另一方面,没有其他任何明确消除勇士的东西,所以你必须深入挖掘。你会发现它被隐藏在except
查询中,它有效地将勇士视为自己玩。这就是勇敢者如何被排除在考虑范围之外,很容易错过。
我希望你不要觉得这很迂腐。从表面上看,作为关于棒球的家庭作业问题,沿着这条路走下去是一个学术问题。我确实认为,在工作场所的其他环境中,您可以轻松地发现这一点非常重要且值得考虑。这是未被发现的错误的一种方式很容易蔓延到已部署的代码中。