2009-02-17 3 views
0

Я строю этот отчет в системе для компании Billboard. У них есть таблица, в которой хранятся все их рекламные щиты, а среди других данных на рекламных щитах есть дата начала и дата окончания (оба могут быть нулевыми).
Если по какой-то причине рекламный щит должен прекратить использоваться, они устанавливают дату окончания, и после этой даты он станет ненужным. То же самое с датой начала (в случае, если они просто настроили новую плату, и она будет доступна для использования после установленной даты начала).SQL Looping

В этом отчете я должен получить сумму всех возможных рекламных площадок за определенный период времени.

Таким образом, позволяет сказать, что за период я ​​выбрал (4 недели, для Exemple)
* В 1-й неделе есть 500 Avaiable доски
* В неделю 2 один борт стал недоступной (изготовление 498 досок Avaiable)
* В неделю 3 две доски стали доклада доступен (изготовление 501 досок Avaiable)
* В неделю 4 один борт стал доклада доступен и одна другая стала недоступной (изготовление 501 досок Avaiable)

Итак, я должен иметь в общей сложности 1990 Avaiable досок в этот период я ​​получил результат.

Как я могу получить это в одном запросе?
Неделю придет из HTML-формы, и я должен преобразовать их в даты перед запросом, поэтому у меня будут только даты, когда я хочу знать, сколько плат доступно.
Запрос, чтобы получить количество досок для одной конкретной даты, как это:

SELECT 
    COUNT(IdBillboard) 
FROM 
    tBillboards 
WHERE 
    (StartDate IS NULL OR StartDate <= '2009-01-05 00:00:00') 
    AND (FinishDate IS NULL OR FinishDate >= '2009-01-05 00:00:00') 

Я не могу просто добавить AND и OR условными на каждую дату, потому что я вроде нужен новый подсчёт для отдельных дат. Я думал об использовании WHILE, но не мог точно определить, как это сделать для этого случая. Так вот, где я застрял ... Я отправлю более подробную информацию, если кому-то это понадобится.

Спасибо, Гейб

+0

Я думаю, вы имели в виду 498 плат в неделю 2. – achinda99

+0

Ха-ха. Починил это. Спасибо – Gabe

+0

Все ли всегда делится на неделю? –

ответ

3

Не знаю, если это то, что вы ищете, но может быть шагом в правильном направлении.

SELECT 
    SUM(CASE WHEN 
    (StartDate IS NULL OR StartDate <= '2009-01-05 00:00:00') 
     AND (FinishDate IS NULL OR FinishDate >= '2009-01-05 00:00:00') 
    THEN 1 
    ELSE 0 END)) Week1Count, 
    SUM(CASE WHEN 
    (StartDate IS NULL OR StartDate <= '2009-01-12 00:00:00') 
     AND (FinishDate IS NULL OR FinishDate >= '2009-01-12 00:00:00') 
    THEN 1 
    ELSE 0 END)) Week2Count 
FROM 
    tBillboards 
+0

Спасибо, Барри! Я даже не думал о том, чтобы привести результаты в разные столбцы. Но это все еще не идеально. Фундаментация группировки должна быть SUM вместо COUNT, и после этого предложение where не имеет особого значения. Если вы отредактируете его, чтобы я мог проверить, как принято, я буду более чем рад сделать это – Gabe

+0

Да, я как бы бросил ответ. Отредактировано сейчас. – Barry

0

Если вы можете получить дату из формы в (возможно, временно) таблицы, то ваш запрос может быть:

SELECT 
    COUNT(t.IdBillboard) 
FROM 
    tBillboards r, tDates d 
WHERE 
    (t.StartDate IS NULL OR StartDate <= d.date) 
    AND (t.FinishDate IS NULL OR FinishDate >= d.date) 
0
SELECT COUNT(*) 
FROM 
    (
    SELECT DATEADD(ww, num, @initdate) AS wd 
    FROM (
     SELECT 0 AS num 
     UNION ALL 
     SELECT 1 
     UNION ALL 
     SELECT 2 
     UNION ALL 
     SELECT 3 
     ) w 
    ) weeks, Billboards bb 
WHERE wd BETWEEN NULLIF(bb.StartDate, wd) AND NULLIF(bb.EndDate, wd) 
1

Это не ответ на ваш вопрос, но вы должны рассмотрите возможность использования BETWEEN вместо AND с.

WHERE 
    (StartDate IS NULL) OR 
    StartDate BETWEEN '2009-01-05' AND '2009-01-05' 

IMO это более читаемо.

0

В SQL отсутствует WHILE. В цикле вы присоединяетесь к другой таблице.

Вы не указали это, но я полагаю, что рекламные щиты меняют доступность в один день недели, говорят в воскресенье, и они не могут меняться несколько раз в неделю.

Что вам нужно сделать, так это создать таблицу всех возможных недель, когда это изменение может произойти, назовем его DT для даты, с одним столбцом даты x, который имеет одну дату в неделю (воскресенье?).

Затем сделать что-то вроде этого:

select count(*) from tBillboards b 
inner join DT d 
    on (b.startdate is null or b.startdate <= d.x) 
     and (b.finishdate is null or b.finishdate < d.x) 
where d.x between period_start and period_end 
0

Предполагая, что вы используете SQL Server 2005 или более поздней версии, вы можете сделать это с помощью КТР, как показано в следующем примере. В моем примере вам необходимо установить дату и количество недель, которые вы хотите, чтобы оглянуться назад с этой датой:

DECLARE @dtNow DATETIME 
DECLARE @iNumberOfWeeks INT 
SET @dtNow = '2009-01-21' 
SET @iNumberOfWeeks = 2; 


WITH CountForPeriod (IdBillBoard, StartDate, FinishDate, NumberOfWeeksBack) AS 
(
    SELECT IdBillBoard, StartDate, FinishDate, 1 AS NumberOfWeeksBack 
    FROM tBillBoards 
    WHERE (StartDate <= @dtNow) 
    AND (FinishDate >= @dtNow) 

    UNION ALL 

    SELECT b.IdBillBoard, b.StartDate, b.FinishDate, 1 + NumberOfWeeksBack 
    FROM tBillBoards b 
    JOIN CountForPeriod c 
    ON (b.StartDate <= DATEADD(dd, -7 * c.NumberOfWeeksBack, @dtNow)) 
    AND (b.FinishDate >= DATEADD(dd, -7 * c.NumberOfWeeksBack, @dtNow)) 
) 
SELECT NumberOfWeeksBack, COUNT(*) 
FROM CountForPeriod 
WHERE NumberOfWeeksBack <= @iNumberOfWeeks 
GROUP BY NumberOfWeeksBack 
0

Это даст вам общее количество в течение первых 4 недель в 2009 году, чтобы проверить еще на один год измените два вхождения 2009 в запросе ниже год вы заинтересованы.

select sum(Count) as Total 
from (
    SELECT w.Week, Count(*) as Count 
    FROM tBillboards b 
    inner join (
     select 1 as Week 
     union all 
     select 2 
     union all 
     select 3 
     union all 
     select 4 
    ) w on StartDate is null or datepart(ww, StartDate) <= w.Week 
     and FinishDate is null or datepart(ww, FinishDate) >= w.Week 
    where isnull(year(StartDate), 2009) <= 2009 
     and isnull(year(FinishDate), 2009) >= 2009 
    group by w.Week 
) a 

Если вам нужно больше, чем первые 4 недели, продолжают добавлять номера на внутренний запрос с союзами в нем.