【问题标题】:SQL to count distinct sets, reusing rows multiple timesSQL 计算不同的集合,多次重用行
【发布时间】:2014-03-01 06:29:18
【问题描述】:

我正在尝试编写一个查询或一组查询来计算跨越多行的唯一集,但行中的数据可能需要计算多次。

在以下集合中,我想要按年份分组的以下计数

Number of unique SID, Year, Flag1  //2013=2, 2014=2
Number of unique SID, Year, Flag2  //2013=1, 2014=0
Number of unique SID, Year, Flag3  //2013=1, 2014=2

然后我想做同样的事情,按年/月分组

Number of unique SID, Year, Month, Flag1  //2013-Jan=2, 2013-Feb=2, 2013-Mar=1, etc
Number of unique SID, Year, Month, Flag2  //2013-Jan=1, 2013-Feb=1, 2013-Mar=1, etc
Number of unique SID, Year, Month, Flag3, //2013-Jan=1, 2013-Feb=1, 2013-Mar=1, etc

数据集

SID    Year     Month     Flag1     Flag2     Flag3
--------------------------------------------------
1      2013     Jan         Y         Y         Y
1      2013     Feb         Y         Y         Y
1      2013     Mar         Y         Y         Y
1      2014     Jan         Y                   Y
1      2014     Feb         Y 
2      2013     Jan         Y 
2      2013     Feb         Y  
2      2014     Jan         Y                   Y      
2      2014     Feb         Y                   Y     

我可以对每个计数使用一个查询来做到这一点,但我真的很想将它合并到一个查询中。

我今年的多次统计如下:

select count(*) from 
( select distinct SID, Year, Flag1 from Table WHERE Year = '2013' ) as 2013Flag1

select count(*) from 
( select distinct SID, Year, Flag2 from Table WHERE Year = '2013' ) as 2013Flag2

select count(*) from 
( select distinct SID, Year, Flag1 from Table WHERE Year = '2014' ) as 2014Flag1

等等……

月份计数如下所示:

select count(*) from 
( select distinct SID, Year, Month, Flag1 from Table WHERE Year = '2013' and Month = 'Jan' ) as 2013JanFlag1

等等……

查询每个计数是否更容易做到这一点,还是我可以选择某种类型的笛卡尔积?任何想法都会很棒。这来自 Oracle 数据库。我相信它是10g版本。

【问题讨论】:

  • 试试select year, count(distinct sid) from tableName group by year

标签: sql oracle count sum


【解决方案1】:
 SELECT G.SID, G.YEAR, G.MONTH, G.FLAG, COUNT(*)
 FROM (
 SELECT Y.YEAR, Y.SID, Y.MONTH, 1 AS FLAG
 (SELECT DISTINCT SID, YEAR FROM TABLE) AS Y
 JOIN TABLE AS F
   ON F.YEAR = Y.YEAR
  AND F.FLAG1 = 'Y'
 UNION ALL
 SELECT Y.YEAR, Y.SID, Y.MONTH, 2 AS FLAG
 (SELECT DISTINCT SID, YEAR FROM TABLE) AS Y
 JOIN TABLE AS F
   ON F.YEAR = Y.YEAR
  AND F.FLAG2 = 'Y'
 UNION ALL
 SELECT Y.YEAR, Y.SID, Y.MONTH, 3 AS FLAG
 (SELECT DISTINCT SID, YEAR FROM TABLE) AS Y
 JOIN TABLE AS F
   ON F.YEAR = Y.YEAR
  AND F.FLAG3 = 'Y' ) AS G
  GROUP BY G.SID, G.YEAR, G.FLAG, G.MONTH
  ORDER BY G.SID, G.YEAR, G.FLAG, G.MONTH

【讨论】:

    【解决方案2】:

    我没有得到关于标志的逻辑,但也许 ROLLUP 或 CUBE 使查询更容易和更快。

    以下语句是等价的:

    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, flag2, flag3
    FROM a_table
    GROUP BY flag1, flag2, flag3, ROLLUP(YEAR, MONTH);
    
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, flag2, flag3
    FROM a_table
    GROUP BY flag1, flag2, flag3, YEAR, MONTH
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, NULL AS MONTH, flag1, flag2, flag3
    FROM a_table
    GROUP BY flag1, flag2, flag3, YEAR
    UNION ALL
    SELECT COUNT(DISTINCT SID), NULL AS YEAR, NULL AS MONTH, flag1, flag2, flag3
    FROM a_table
    GROUP BY flag1, flag2, flag3;
    

    CUBE 的另一个例子:

    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, flag2, flag3, GROUPING_ID(flag1, flag2, flag3) AS flag_ID
    FROM a_table
    GROUP BY YEAR, MONTH, CUBE(flag1, flag2, flag3)
    
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, flag2, flag3, 0 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag1, flag2, flag3 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, flag2, NULL AS flag3, 1 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag1, flag2 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, NULL AS flag2, flag3, 2 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag1, flag3 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, flag1, NULL AS flag2, NULL AS flag3, 3 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag1 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, NULL AS flag1, flag2, flag3, 4 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag2, flag3 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, NULL AS flag1, flag2, NULL AS flag3, 5 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag2 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, NULL AS flag1, NULL AS flag2, flag3, 6 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH, flag3 
    UNION ALL
    SELECT COUNT(DISTINCT SID), YEAR, MONTH, NULL AS flag1, NULL AS flag2, NULL AS flag3, 7 AS flag_id 
    FROM a_table 
    GROUP BY YEAR, MONTH
    

    您可以在一个 GROUP BY 子句中同时使用 ROLLUP 和 CUBE。

    您可以在此处找到 ROLLUP 和 CUBE 子句文档:http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#SQLRF55331

    检查功能还包括GROUPING_IDGROUPING。例如,您可以在 HAVING 子句中使用它来根据您的需要限制输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      相关资源
      最近更新 更多