Sql server 对来自联合的SQL结果进行分组(SQL Server)
我对Sql server 对来自联合的SQL结果进行分组(SQL Server),sql-server,group-by,union,Sql Server,Group By,Union,我对分组依据和联合使用重复查询来获得结果,但结果并不像我想要的那样显示 查询: select league , count(*) as total_1 from Games where score_away is not null and score_home is not null group by League union select league , count(*) as total_
分组依据
和联合
使用重复查询来获得结果,但结果并不像我想要的那样显示
查询:
select
league ,
count(*) as total_1
from
Games
where
score_away is not null
and score_home is not null
group by
League
union
select
league ,
count(*) as total_2
from
Games
where
score_away is null
and score_home is null
group by
League
游戏表
leugue gameID score_home score_away
-------------------------------------------------
1 10 2 0
1 11 1 1
1 12 NUll NULL
2 13 2 0
1 14 NUll NULL
1 15 1 1
2 16 2 2
2 17 2 4
目前的结果:
League total1
------------------------
1 3
1 2
2 3
预期成果:
League total1 total2
-------------------------------
1 3 2
2 3 0
如果需要所有结果(不删除重复项),则可能希望使用UNION all而不是UNION。在这种情况下,结果将变成:
League total1
------------------------
1 20
2 10
1 40
2 10
但是,要获得所需的结果,您可能需要尝试:
SELECT
league = COALESCE(Totals1.league, Totals2.league),
total_1 = COALESCE(Totals1.total_1, 0),
total_2 = COALESCE(Totals2.total_2, 0)
FROM
(SELECT league, COUNT(*) as total_1
FROM Games
WHERE score_away is not null and score_home is not null
GROUP BY league) as Totals1
FULL JOIN
(SELECT league, COUNT(*) as total_2
FROM Games
WHERE score_away is null and score_home is null
GROUP BY league) as Totals2
ON Totals1.league = Totals2.league;
编辑:只是对结果中的总数进行了修正,使其返回0而不是NULL
编辑2:
根据您在评论中请求的扩展,我修改了我的查询,将百分比计算包括在内,如下所示:
SELECT
league = COALESCE(Totals1.league, Totals2.league),
total_1 = COALESCE(Totals1.total_1, 0),
total_2 = COALESCE(Totals2.total_2, 0),
percent_1 = 100 * COALESCE(Totals1.total_1, 0) / (COALESCE(Totals1.total_1, 0) + COALESCE(Totals2.total_2, 0)),
percent_2 = 100 * COALESCE(Totals2.total_2, 0) / (COALESCE(Totals1.total_1, 0) + COALESCE(Totals2.total_2, 0))
FROM
(SELECT league, COUNT(*) AS total_1
FROM Games
WHERE score_away IS NOT NULL AND score_home IS NOT NULL
GROUP BY league) AS Totals1
FULL JOIN
(SELECT league, COUNT(*) as total_2
FROM Games
WHERE score_away IS NULL AND score_home IS NULL
GROUP BY league) AS Totals2
ON Totals1.league = Totals2.league
ORDER BY percent_1;
为了使百分比计算更具可读性,可以将原始查询作为子查询放置在表表达式中。像这样:
SELECT
league,
total_1,
total_2,
percent_1 = 100 * total_1 / (total_1 + total_2),
percent_2 = 100 * total_2 / (total_1 + total_2)
FROM
(
SELECT
league = COALESCE(Totals1.league, Totals2.league),
total_1 = COALESCE(Totals1.total_1, 0),
total_2 = COALESCE(Totals2.total_2, 0)
FROM
(SELECT league, COUNT(*) AS total_1
FROM Games
WHERE score_away IS NOT NULL AND score_home IS NOT NULL
GROUP BY league) AS Totals1
FULL JOIN
(SELECT league, COUNT(*) as total_2
FROM Games
WHERE score_away IS NULL AND score_home IS NULL
GROUP BY league) AS Totals2
ON Totals1.league = Totals2.league
) AS Sub
ORDER BY percent_1;
我个人不喜欢FROM子句中复杂的“匿名”表表达式,并将其转换为公共表表达式,如下所示:
WITH
Sub AS
(
SELECT
league = COALESCE(Totals1.league, Totals2.league),
total_1 = COALESCE(Totals1.total_1, 0),
total_2 = COALESCE(Totals2.total_2, 0)
FROM
(SELECT league, COUNT(*) AS total_1
FROM Games
WHERE score_away IS NOT NULL AND score_home IS NOT NULL
GROUP BY league) AS Totals1
FULL JOIN
(SELECT league, COUNT(*) as total_2
FROM Games
WHERE score_away IS NULL AND score_home IS NULL
GROUP BY league) AS Totals2
ON Totals1.league = Totals2.league
)
SELECT
league,
total_1,
total_2,
percent_1 = 100 * total_1 / (total_1 + total_2),
percent_2 = 100 * total_2 / (total_1 + total_2)
FROM Sub
ORDER BY percent_1;
当像这样重构查询时,我还会将其他两个表表达式(游戏表上的两个SELECT子查询)转换为公共表表达式:
WITH
Totals1 AS
(
SELECT league, COUNT(*) AS total_1
FROM Games
WHERE score_away IS NOT NULL AND score_home IS NOT NULL
GROUP BY league
),
Totals2 AS
(
SELECT league, COUNT(*) as total_2
FROM Games
WHERE score_away IS NULL AND score_home IS NULL
GROUP BY league
),
Sub AS
(
SELECT
league = COALESCE(Totals1.league, Totals2.league),
total_1 = COALESCE(Totals1.total_1, 0),
total_2 = COALESCE(Totals2.total_2, 0)
FROM
Totals1
FULL JOIN Totals2 ON Totals1.league = Totals2.league
)
SELECT
league,
total_1,
total_2,
percent_1 = 100 * total_1 / (total_1 + total_2),
percent_2 = 100 * total_2 / (total_1 + total_2)
FROM Sub
ORDER BY percent_1;
当然,通过将原始查询放在公共表表达式中,也可以对来自LukStorms的原始查询执行相同的操作:
WITH
Sub AS
(
SELECT
league,
total_1 = SUM(CASE WHEN score_away IS NOT NULL AND score_home IS NOT NULL THEN 1 ELSE 0 END),
total_2 = SUM(CASE WHEN score_away IS NULL AND score_home IS NULL THEN 1 ELSE 0 END)
FROM Games
GROUP BY league
)
SELECT
league,
total_1,
total_2,
percent_1 = 100 * total_1 / (total_1 + total_2),
percent_2 = 100 * total_2 / (total_1 + total_2)
FROM Sub
ORDER BY percent_1;
在我看来,在这种情况下,LukStorms的查询更短、更优雅,而且可能更快
注1:百分比目前是整数。如果需要分数百分比,可以用100.0替换100
注2:在SQL脚本或存储过程中使用公共表表达式(使用WITH子句)时,请注意,需要用分号分隔上一个查询(WITH关键字之前)。否则,SQL Server将抱怨出现错误。您实际上可以在不使用联合或联接的情况下执行此类操作。
只需使用GROUP BY并将计算出的1或0相加(通过案例或IIF) 然后,使用相同的技巧添加额外的总数将变得更容易。 示例代码片段: 仍然可以使用UNION ALL进行此操作。
只需在联合中使用的选择中添加一个额外字段。
然后将结果分组 例如: 但这是一种效率较低的方法。
(顺便说一句,
UNION
删除重复项,但UNION ALL
不删除重复项)使用联接而不是并集。请注意,联赛2的预期结果中的一个总数应该为空。如果您能向我们展示表格结构,会更容易。(参考)不客气。也许这不是最优雅的解决方案,但这是我能想到的第一个解决方案。我也喜欢LukStorms的答案。它更短,可能更快。我可以添加另一个Coulmn,前面的total1/total2,然后从大到小(按新列排序)?@alex1121可能。如果是这样,结果集中的total2可能永远不会为零,因为除以零将导致错误。在您的情况下,要求每个联赛值在表中至少有一条记录,其中客场得分和主场得分值均为空。。。是这样吗?@alex1121我假设在尚未进行的比赛中,客场和主场的比分都是空的。所以我假设total_1是已玩游戏的数量,total_2是仍要玩游戏的数量(对于某个联赛)。你能证实或否认这一点吗?这将导致对你的问题有一个新的理解和新的观点。
select
league,
sum(case when score_away is not null and score_home is not null then 1 else 0 end) as total1_has_away_and_home,
sum(iif(score_away is null and score_home is null, 1, 0)) as total2_no_away_or_home
from Games g
group by league;
declare @Games table (league int, gameID int, score_home int, score_away int);
insert into @Games (league, gameID, score_home, score_away) values
(1, 10, 2, 0),(1, 11, 1, 1),(1, 12, NULL, NULL),(1, 14, NULL, NULL),(1, 15, 1, 1),
(2, 13, 2, 0),(2, 16, 2, 2),(2, 17, 2, 4);
select
league,
sum(case when score_away is not null and score_home is not null then 1 else 0 end) as total1_has_away_and_home,
sum(case when score_away is null and score_home is null then 1 else 0 end) as total2_no_away_or_home
from @Games g
group by league;
select league, sum(total_1) as total_1, sum(total_2) as total_2
from
(
select league, count(*) as total_1, 0 as total_2
from Games
where score_away is not null
and score_home is not null
group by league
union all
select league, 0, count(*)
from Games
where score_away is null
and score_home is null
group by league
) q
group by league;