Какой-либо из этих запросов может быть сделан в SQL?
SELECT dates FROM system
WHERE dates > 'January 5, 2010' AND dates < 'January 30, 2010'
SELECT number FROM system
WHERE number > 10 AND number < 20
Я хотел бы создать a generate_series
, и вот почему я спрашиваю.
Я предполагаю, что вы хотите сгенерировать набор записей с произвольным количеством значений, основанный на первом и последнем значении в серии.
В PostgreSQL
:
SELECT num
FROM generate_series (11, 19) num
В SQL Server
:
WITH q (num) AS
(
SELECT 11
UNION ALL
SELECT num + 1
FROM q
WHERE num < 19
)
SELECT num
FROM q
OPTION (MAXRECURSION 0)
В Oracle
:
SELECT level + 10 AS num
FROM dual
CONNECT BY
level < 10
В MySQL
:
Извините.
Типа дат ... Майкл Валентайн Джонс из команды SQL имеет УДИВИТЕЛЬНУЮ функцию даты
Проверьте это здесь:
В SQL Server вы можете использовать ключевое слово BETWEEN
.
Ссылка: http://msdn.microsoft.com/nl-be/library/ms187922(en-us).aspx
Не уверен, что это именно то, что вы спрашиваете, но если вы хотите выбрать что-то не из таблицы, вы можете использовать 'DUAL'
select 1, 2, 3 from dual;
вернет строку с 3 столбцами, содержащую эти три цифры.
Выбор из двойного полезно для выполнения функций. Функцию можно запускать с ручным вводом вместо того, чтобы выбирать в ней что-то еще. Например:
select some_func('First Parameter', 'Second parameter') from dual;
вернет результаты some_func.
Вы можете выбрать диапазон, используя ГДЕ
и И ГДЕ
. Я не могу говорить о производительности, но это возможно.
В Oracle
WITH
START_DATE AS
(
SELECT TO_CHAR(TO_DATE('JANUARY 5 2010','MONTH DD YYYY'),'J')
JULIAN FROM DUAL
),
END_DATE AS
(
SELECT TO_CHAR(TO_DATE('JANUARY 30 2010','MONTH DD YYYY'),'J')
JULIAN FROM DUAL
),
DAYS AS
(
SELECT END_DATE.JULIAN - START_DATE.JULIAN DIFF
FROM START_DATE, END_DATE
)
SELECT TO_CHAR(TO_DATE(N + START_DATE.JULIAN, 'J'), 'MONTH DD YYYY')
DESIRED_DATES
FROM
START_DATE,
(
SELECT LEVEL N
FROM DUAL, DAYS
CONNECT BY LEVEL < DAYS.DIFF
)
Если вы хотите получить список дней, используйте SQL типа
select ... as days where date
is between '2010-01-20' and '2010-01-24'
И верните данные типа:
days
----------
2010-01-20
2010-01-21
2010-01-22
2010-01-23
2010-01-24
Это решение не использует циклы, процедуры или временные таблицы. Подзапрос генерирует даты за последнюю тысячу дней, и может быть расширен для возврата назад или вперед по вашему желанию.
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date between '2010-01-20' and '2010-01-24'
Вывод:
Date
----------
2010-01-24
2010-01-23
2010-01-22
2010-01-21
2010-01-20
Замечания по производительности
Протестировав его здесь, можно сказать, что производительность удивительно хорошая: вышеприведенный запрос занимает 0,0009 сек.
Если мы расширим подзапрос для генерации примерно 100 000 чисел (и, соответственно, дат за 274 года), он выполняется за 0,0458 сек.
Кстати, это очень портативная техника, которая работает с большинством баз данных с небольшими корректировками.
Простейшим решением этой проблемы является таблица Tally или Numbers. Это таблица, которая просто хранит последовательность целых чисел и/или дат
Create Table dbo.Tally (
NumericValue int not null Primary Key Clustered
, DateValue datetime NOT NULL
, Constraint UK_Tally_DateValue Unique ( DateValue )
)
GO
;With TallyItems
As (
Select 0 As Num
Union All
Select ROW_NUMBER() OVER ( Order By C1.object_id ) As Num
From sys.columns as c1
cross join sys.columns as c2
)
Insert dbo.Tally(NumericValue, DateValue)
Select Num, DateAdd(d, Num, '19000101')
From TallyItems
Where Num
Как только вы заполните эту таблицу, вам никогда не придется к ней прикасаться, если только вы не захотите ее расширить. Я объединил даты и числа в одну таблицу, но если вам нужно больше чисел, чем дат, то вы можете разбить ее на две таблицы. Кроме того, я произвольно заполнил таблицу 100K строк, но вы можете добавить больше. Каждый день с 1900-01-01 по 9999-12-31 занимает около 434K строк. Вероятно, вам не понадобится столько, но даже если и понадобится, хранилище будет крошечным.
Независимо от этого, это обычная техника для решения многих проблем с пробелами и последовательностями. Например, все ваши исходные запросы выполнялись менее чем за десятые доли секунды. Вы также можете использовать такую таблицу для решения проблем с пробелами, например:
Select NumericValue From dbo.Tally Left Join MyTable On Tally.NumericValue = MyTable.IdentityColumn Where Tally.NumericValue Between SomeLowValue And SomeHighValue