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;