SQL-запрос на основе цикла while - PullRequest
2 голосов
/ 22 июля 2011

Я пытаюсь создать SQL-запрос, используя цикл while, который увеличивает дату и время на одну минуту каждую итерацию, а затем генерирует оператор выбора на основе времени:

declare @dt datetime
set @dt = '2011-7-21'
while @dt < '2011-7-22'
begin
    select Count(*) From Actions Where Timestamp = @dt
    set @dt = DATEADD(mi, 1, @dt)
end

Запрос работает, как и предполагалось, за исключениемчто каждая итерация цикла while создает новый запрос полностью, а не просто новую строку.Есть ли способ построить это так, чтобы его один запрос и каждая строка генерировались путем увеличения цикла?Я полагаю, что это происходит потому, что оператор select находится внутри цикла, но я не уверен, как создать его другим способом, который работает.

РЕДАКТИРОВАТЬ - Вот то, что я придумал, используя временную таблицу, но это медленно.Может быть, есть более быстрый способ?Если это не так, по крайней мере, это работает:

create table #temp 
(
  [DT] datetime not null,
  [Total] int not null
)

declare @dt datetime
declare @result int
set @dt = '2011-7-21'
while @dt < '2011-7-22'
begin
    set @result = Count(*) From Actions Where Timestamp = @dt
    insert #temp ([DT],[Total]) values (@dt, @result)
    set @dt = DATEADD(mi, 1, @dt)
end

select * from #temp;

drop table #temp; 

Ответы [ 2 ]

1 голос
/ 22 июля 2011

Если у вас есть таблица чисел (от 0 до миллиона или что-то еще), это относительно просто:

SELECT *
FROM Numbers AS n
LEFT JOIN (
    SELECT Timestamp, COUNT(*) AS Ct
    FROM Actions
    GROUP BY Timestamp
) AS ActionSummary
    ON ActionSummary.Timestamp = DATEADD(mi, n.Number, '2011-07-21')
WHERE DATEADD(mi, n.Number, '2011-07-21') < '2011-07-22'
ORDER BY DATEADD(mi, n.Number, '2011-07-21')

Нет необходимости в циклах.

Есть способы оптимизировать это,но это должно быть вполне понятно.

Также обратите внимание, что у меток времени не должно быть секунд или долей секунды, чтобы это работало (у вашего оригинала также есть эта проблема).

1 голос
/ 22 июля 2011

В одну сторону с помощью таблицы чисел

declare @dt datetime
set @dt = '2011-07-21'

select DATEADD(mi, number, @dt) 
from master..spt_values
where type = 'P'
and DATEADD(mi, number, @dt)  < '2011-07-22'

Если у вас есть собственная таблица номеров, используйте эту

Для получения дополнительной информации см. Здесь http://wiki.lessthandot.com/index.php/Date_Ranges_Without_Loops

Ваш полный запрос будет выглядеть как

DECLARE @dt DATETIME
SET @dt = '2011-07-21'

SELECT x.SomeTime,y.TheCount FROM 
(SELECT DATEADD(mi, number, @dt) as SomeTime FROM master..spt_values
WHERE TYPE = 'P'
AND DATEADD(mi, number, @dt)  < '2011-07-22') x
LEFT JOIN (
    SELECT TIMESTAMP, COUNT(*) AS TheCount
    FROM Actions
    GROUP BY TIMESTAMP
) AS y
ON x.SomeTime = dateadd(mi, datediff(mi, 0, y.Timestamp)+0, 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...