2010-04-22 1 views
1

Предположим, что есть таблица, в которой хранится количество посетителей за каждый день.Строки SQL Date для дней бездействия

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

Дни без активности не имеют соответствующих строк на столе.

Например

Day1 - 7 
Day2 - 8 
Day4 - 7 

и график генерируемой не будет правильным. Поскольку для Day3 требуется 0.

Теперь, не используя ничего, кроме SQL, можно создать эти значения для дней бездействия?

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

Заранее спасибо.

+1

SQL Server? MySQL? Что-то другое? –

+1

Возможный дубликат http: // stackoverflow.com/questions/75752/what-is-the-most-straight-way-to-pad-empty-dates-in-sql-results-on-both - этот вопрос был задан очень много на SO. Как правило, ответ заключается в объединении с временной таблицей, содержащей все ваши даты, или обработкой недостающих значений в логике приложения. – zombat

+1

Другой вопрос, похожий на этот: http://stackoverflow.com/questions/2670183/displaying-zero-valued-months-with-sql –

ответ

1

Ваше решение о создании таблицы с 30 днями - это очень простое и практичное решение.

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

0

Нет, нет стандартного способа использования только SQL, чтобы добавить неопределенное количество отсутствующих строк в результат SQL-запроса без предварительного хранения этих строк в таблице.

Либо у вас может быть одна таблица, которая содержит все даты, над которыми будет работать ваше приложение, или вы можете иметь таблицу, в которую вы помещаете только даты, которые будет использоваться вашим текущим запросом. Если вы выберете второе решение, не забудьте планировать для разных пользователей, выполняющих один и тот же запрос, с разными диапазонами дат одновременно - вы хотите, чтобы таблица была временной и пользовательской, если ваша СУБД поддерживает это.

1

Использование SQL Server 2005+ и КТР Рекурсивный (Using Common Table Expressions) вы можете попробовать

DECLARE @Table TABLE(
     DateVal DATETIME, 
     Visists INT 
) 

INSERT INTO @Table SELECT '01 Jan 2010', 10 
INSERT INTO @Table SELECT '03 Jan 2010', 1 
INSERT INTO @Table SELECT '05 Jan 2010', 30 
INSERT INTO @Table SELECT '10 Jan 2010', 50 

;WITH MinMax AS (
     SELECT MIN(DateVal) Startdate, 
       MAX(DateVal) EndDate 
     FROM @Table 
), 
DateRange AS(
     SELECT StartDate DateVal 
     FROM MinMax 
     UNION ALL 
     SELECT DateRange.DateVal + 1 
     FROM DateRange, 
       MinMax 
     WHERE DateRange.DateVal + 1 <= MinMax.EndDate 
) 
SELECT DateRange.DateVal, 
     ISNULL(t.Visists,0) TotalVisits 
FROM DateRange LEFT JOIN 
     @Table t ON DateRange.DateVal = t.DateVal 

С выходом в

DateVal     TotalVisits 
----------------------- ----------- 
2010-01-01 00:00:00.000 10 
2010-01-02 00:00:00.000 0 
2010-01-03 00:00:00.000 1 
2010-01-04 00:00:00.000 0 
2010-01-05 00:00:00.000 30 
2010-01-06 00:00:00.000 0 
2010-01-07 00:00:00.000 0 
2010-01-08 00:00:00.000 0 
2010-01-09 00:00:00.000 0 
2010-01-10 00:00:00.000 50 
1

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

PostgreSQL имеет хорошую функцию: generate_series

Вы можете использовать эту функцию, чтобы создать серию 30 дней.

select current_date + s.a as dates from generate_series(0,30) as s(a); 

dates  
------------ 
2010-04-22 
2010-04-23 
2010-04-24 
(.. etc ..) 

Вы можете использовать это в запросе, что-то вроде:

select vpd.visits, temp.dates 
    from (select current_date + s.a as dates from generate_series(0,30) as s(a)) as temp 
left outer join visits_per_day vpd on vpd.day = temp.dates 

visits | dates  
--------+------------ 
    10 | 2010-04-22 
     | 2010-04-23 
    20 | 2010-04-24 
     | 2010-04-25 
     | 2010-04-26 
    30 | 2010-04-27