SQL: как сделать условный COUNT и SUM - PullRequest
2 голосов
/ 15 августа 2011

Допустим, у меня есть следующая таблица:

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 ]

2 голосов
/ 15 августа 2011

Примечание Я не заметил, что это был 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 голос
/ 16 августа 2011

Небольшое отклонение от предыдущего:

    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
1 голос
/ 15 августа 2011

Требование

каждая буква должна иметь строку с каждой датой таблицы

требует перекрестного соединения различных дат и букв.Как только вы это сделаете, это довольно просто

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 
...