SQL выбирает и подсчитывает все элементы, которые произошли до

У меня есть таблица со строками, которые символизируют даты заказа:

2009-05-15 13:31:47.713 
2009-05-15 22:09:32.227
2009-05-16 02:38:36.027
2009-05-16 12:06:49.743
2009-05-16 16:20:26.680
2009-05-17 01:36:19.480
2009-05-18 09:44:46.993
2009-05-18 14:06:12.073 
2009-05-18 15:25:47.540
2009-05-19 10:28:24.150 

Я хотел бы иметь запрос, который возвращает следующее:

2009-05-15 2
2009-05-16 5
2009-05-17 6
2009-05-18 9
2009-05-19 10

В основном он хранит текущую сумму всех заказов, размещенных к концу дня указанной даты. Заказы - это не заказы в этот день, а все заказы с самых ранних дат в таблице.

Это MSSQL 2000, и тип данных в первой таблице — это просто дата и время, во второй это может быть дата и время или строка, это не имеет большого значения для моих целей.


person Matt    schedule 12.08.2009    source источник
comment
Смотрите мои правки выше (нижняя часть поста)   -  person Matt    schedule 13.08.2009


Ответы (5)


Я заставил это работать на SQL Server 2005. Я думаю, что это должно работать и с 2000.

SELECT dt, count(q2.YourDate)
    FROM (SELECT DISTINCT CONVERT(varchar,YourDate,101) dt FROM YourTable) t1
    JOIN YourTable q2 ON DATEADD(d,-1,CONVERT(varchar,YourDate,101)) < dt
    GROUP BY dt

Это дважды запросит таблицу, но, по крайней мере, даст правильный результат.

person JamesMLV    schedule 12.08.2009
comment
+1, то же базовое решение для соединения, что и у меня, но без дополнительной производной таблицы. хорошее компактное решение! - person KM.; 13.08.2009
comment
+1 и здесь, то же самое базовое решение для соединения, что и у меня, но гораздо более компактное и специфичное для Tsql для загрузки. - person PowerUser; 13.08.2009

Я рекомендую решение с двумя запросами. Это медленно, но я использую этот метод почти каждый день. Важно НЕ объединять 2 таблицы в первом запросе. Вы хотите дублировать каждый заказ для каждой даты в вашей таблице поиска.

Вам понадобится таблица поиска с 1 строкой для каждой даты интересующего вас периода времени. Назовем ее dboDateLookup. Вот как это будет выглядеть:

DtIndex  
2009-05-15  
2009-05-16  
2009-05-17  
2009-05-18  
2009-05-19

Давайте также предположим, что таблица заказов, dboOrders имеет 2 столбца, номер заказа и дату заказа.

ordernumber               orderdate   
2009-05-15 13:31:47.713   1  
2009-05-15 22:09:32.227   2  
2009-05-16 02:38:36.027   3  
2009-05-16 12:06:49.743   4  
2009-05-16 16:20:26.680   5

Запрос1:

SELECT  
Format([ordernumber],"yyyy-mm-dd") AS ByDate,  
ordernumber,  
(If Format([orderdate],"yyyy-mm-dd")<=[DtIndex],1,0) AS NumOrdersBefore  
FROM [dboOrders], [dboDateLookUp];

Запрос2:

Select  
[ByDate],  
sum([NumOrdersBefore]) as RunningTotal  
from [Query1];
person PowerUser    schedule 12.08.2009

Попробуйте это (возвращает строковые даты):

SELECT
    LEFT(CONVERT(char(23),YourDate,121),10) AS Date
        ,COUNT(*) AS CountOf
    FROM YourTable
    GROUP BY LEFT(CONVERT(char(23),YourDate,121),10) 
    ORDER BY 1

это будет сканирование таблицы. если это слишком медленно, рассмотрите возможность использования постоянного вычисляемого столбца с индексом для даты, который будет работать намного быстрее. Однако я не уверен, что вы можете сделать все это в SQL 2000.

EDIT прочитайте вопрос лучше, попробуйте следующее:

SELECT
    d.YourDate
        ,SUM(dt.CountOf) AS CountOf
    FROM (SELECT
              LEFT(CONVERT(char(23),YourDate,121),10) AS Date
                  ,COUNT(*) AS CountOf
              FROM YourTable
              GROUP BY LEFT(CONVERT(char(23),YourDate,121),10) 
        ) dt
        INNER JOIN (SELECT
                        DISTINCT LEFT(CONVERT(char(23),YourDate,121),10) AS Date
                        FROM YourTable
                   ) d ON dt.Date<=LEFT(CONVERT(char(23),d.YourDate,121),10)
    GROUP BY d.YourDate
    ORDER BY d.YourDate
person KM.    schedule 12.08.2009
comment
Это даст подсчет по дням, а не подсчет всех вещей до дня в любой данный день. - person Russell Steen; 13.08.2009
comment
@ Рассел Стин, спасибо, я лучше прочитал вопрос, вижу, что редактирование делает то, что хочет OP. - person KM.; 13.08.2009

У меня есть еще один. Он не такой уж и необычный, я запускал его в Access, поэтому синтаксис может немного отличаться. Но, похоже, это работает.

P.S. Я относительно новичок в SQL

Данные:

ID  F1  F2
1   15/05/2009  13:31:47.713
2   15/05/2009  22:09:32.227
3   16/05/2009  02:38:36.027
4   16/05/2009  12:06:49.743
5   16/05/2009  16:20:26.680
6   17/05/2009  01:36:19.480
7   18/05/2009  09:44:46.993
8   18/05/2009  14:06:12.073
9   18/05/2009  15:25:47.540
10  19/05/2009  10:28:24.150

Запрос:

SELECT Table1.F1 AS Dates, SUM(REPLACE(Len(Table1.F2), Len(Table1.F2), 1)) AS Occurred
FROM Table1
GROUP BY Table1.F1;

Результат:

Dates   Occurred
15/05/2009  2
16/05/2009  3
17/05/2009  1
18/05/2009  3
19/05/2009  1
person Community    schedule 12.08.2009

SELECT Count(*), LEFT(CONVERT(char(23),YourDate,121),10) AS Date FROM  
(SELECT  
    DISTINCT LEFT(CONVERT(char(23),YourDate,121),10) AS Date  
    FROM YourTable  
    GROUP BY LEFT(CONVERT(char(23),YourDate,121),10)) x  //Gets the distinct dates.  
INNER JOIN YourTable y on x.Date >= y.Date  
GROUP BY LEFT(CONVERT(char(23),YourDate,121),10) 

Это будет медленно. ОЧЕНЬ ОЧЕНЬ медленно. Я ненавижу думать, какое время работы будет.

person Russell Steen    schedule 12.08.2009
comment
// это не комментарий tsql, используйте -- - person KM.; 13.08.2009
comment
ваша версия медленная, потребовалось 1:19, чтобы вернуть 2402 строки из таблицы из 368 449, где моей потребовалось 2 секунды, чтобы вернуть 2043 строки. ваша версия сообщает об одном выходном дне (количество указано за предыдущую дату), и вы пропустите последний день. - person KM.; 13.08.2009
comment
Я использовал // из-за ошибочного впечатления, что он будет отображаться зеленым на дисплее stackoverflow. Я знаю, что моя версия медленная. Твоих правок еще не было, когда я писал это, и я пытался заставить его продолжить запрос. Ваша версия выглядит хорошо после правок. - person Russell Steen; 13.08.2009
comment
На самом деле я думал, что моя версия будет работать намного медленнее, чем она. Версия @JamesMLV работает за те же 2 секунды, что и моя, но мне нравится его лучше, компактнее. - person KM.; 13.08.2009
comment
Здорово! Спасибо, что подтвердили это для всех - person Russell Steen; 13.08.2009
comment
У меня также есть ненужное предложение Group by в моем внутреннем запросе выбора. - person Russell Steen; 13.08.2009