SQL:如何创建条件COUNT和SUM

时间:2011-08-15 19:15:26

标签: mysql sql count group-by sum

假设我有下表:

id    | letter   | date   
--------------------------------
1     | A        | 2011-01-01
2     | A        | 2011-04-01
3     | A        | 2011-04-01
4     | B        | 2011-01-01
5     | B        | 2011-01-01 
6     | B        | 2011-01-01 

我想计算按字母和日期细分的行数,将所有之前日期的数量相加。每个字母在表格的每个日期都应该有一行(即字母B没有2011-04-01的日期,但仍会出现在结果中)

结果表看起来像这样

letter| date           | total  
--------------------------------
A     | 2011-01-01     | 1
A     | 2011-04-01     | 3
B     | 2011-01-01     | 3 
B     | 2011-04-01     | 3

如何在SQL查询中实现此目的? 谢谢你的帮助!

3 个答案:

答案 0 :(得分:2)

注意 我没注意到它是mysql,它不支持CTE。您可以定义临时表来使用它。


这是一个有趣的问题。你需要加入所有日期的所有字母,然后计算前面的行。如果您不关心为日期计数为0的字母行,您可能只需执行以下操作:

SELECT letter, date, 
    (SELECT COUNT(*) 
     FROM tbl tbl2 
     WHERE tbl2.letter = tbl1.letter
        AND tbl2.date <= tbl1.date) AS total
FROM tbl
ORDER BY date, letter

/ 删除了CTE解决方案 /


没有CTE的解决方案

SELECT tblDates.[date], tblLetters.letter, 
    (SELECT COUNT(*)
     FROM tblData tbl2
     WHERE tbl2.letter = tblLetters.letter
        AND tbl2.[date] <= tblDates.[date]) AS total
FROM (SELECT DISTINCT [date] FROM tblData) tblDates
    CROSS JOIN (SELECT DISTINCT letter FROM tblData) tblLetters
ORDER BY tblDates.[date], tblLetters.letter

答案 1 :(得分:1)

要求

  

每个字母都应该在表格的每个日期都有一行

需要不同日期和字母的交叉连接。一旦你这样做,它非常直接

SELECT letterdate.letter, 
       letterdate.DATE, 
       COUNT(yt.id) total 
FROM   (SELECT letter, 
               date 
        FROM   (SELECT DISTINCT DATE 
                FROM   yourtable) dates, 
               (SELECT DISTINCT letter 
                FROM   yourtable) letter) letterdate 
       LEFT JOIN yourtable yt 
         ON letterdate.letter = yt.letter 
            AND yt.DATE < yt.letter 
GROUP  BY letterdate.letter, 
          letterdate.DATE 

答案 2 :(得分:1)

上一个略有不同:

    declare @table1 table (id int, letter char, date smalldatetime)
    insert into @table1 values (1, 'A', '1/1/2011')
    insert into @table1 values (2, 'A', '4/1/2011')
    insert into @table1 values (3, 'A', '4/1/2011')
    insert into @table1 values (4, 'B', '1/1/2011')
    insert into @table1 values (5, 'B', '1/1/2011')
    insert into @table1 values (6, 'B', '1/1/2011')


    select b.letter, b.date, count(0) AS count_ 
    from (
        select distinct letter, a.date from @table1
        cross join (select distinct date from @table1 ) a 
            ) b     
    join @table1 t1
    on t1.letter = b.letter
    and t1.date <= b.date       
    group by b.letter, b.date
    order by b.letter