SQL计算不同的集合,多次重用行

时间:2014-02-05 01:16:55

标签: sql oracle count sum

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

在下面的集合中,我想要按年度

分组的以下内容
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。

2 个答案:

答案 0 :(得分:0)

 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

答案 1 :(得分:0)

我没有得到关于标志的逻辑,但是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子句中使用,以根据您的需要限制输出。