ВЫБЕРИТЕ любую систему - PullRequest
5 голосов
/ 19 февраля 2010

Можно ли выполнить любой из этих запросов в 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

Я хотел бы создать generate_series, и поэтому я спрашиваю.

Ответы [ 8 ]

12 голосов
/ 19 февраля 2010

Я предполагаю, что вы хотите сгенерировать набор записей произвольного числа значений на основе первого и последнего значения в серии.

В 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)

In Oracle:

SELECT  level + 10 AS num
FROM    dual
CONNECT BY
        level < 10

В MySQL:

Извините.

1 голос
/ 19 февраля 2010

Если вы хотите получить список дней, с SQL, например

, выберите ... в качестве дней, где date находится между '2010-01-20' и '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 с.

Кстати, это очень переносимый метод, который работает с большинством баз данных с небольшими изменениями.

1 голос
/ 19 февраля 2010

В 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
)
1 голос
/ 19 февраля 2010

Сортировка для дат ... Майкл Валентин Джонс из SQL Team имеет УДИВИТЕЛЬНУЮ функцию даты

Проверьте это здесь:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=61519

0 голосов
/ 20 февраля 2010

Самым простым решением этой проблемы является таблица Tally or Numbers. Это таблица, которая просто хранит последовательность целых чисел и / или дат

<code>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 

После того, как эта таблица заполнена, вам не нужно прикасаться к ней, если вы не хотите ее расширять. Я объединил даты и числа в одну таблицу, но если вам нужно больше чисел, чем дат, вы можете разбить их на две таблицы. Кроме того, я произвольно заполнил таблицу 100К строк, но вы, очевидно, могли бы добавить больше. Каждый день с 1900-01-01 по 9999-12-31 занимает около 434 тыс. Строк. Вам, вероятно, не понадобится так много, но даже если бы вы это сделали, хранилище было крошечным.

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

Select NumericValue
From dbo.Tally
    Left Join MyTable
        On Tally.NumericValue = MyTable.IdentityColumn
Where Tally.NumericValue Between SomeLowValue And SomeHighValue
</code>
0 голосов
/ 19 февраля 2010

Вы можете выбрать диапазон, используя WHERE и AND WHERE. Я не могу говорить о производительности, но это возможно.

0 голосов
/ 19 февраля 2010

В SQL Server вы можете использовать ключевое слово BETWEEN.

Ссылка: http://msdn.microsoft.com/nl-be/library/ms187922(en-us).aspx

0 голосов
/ 19 февраля 2010

Не уверен, если это то, что вы спрашиваете, но если вы хотите выбрать что-то не из таблицы, вы можете использовать 'ДВОЙНОЙ'

select 1, 2, 3 from dual;

вернет строку с 3 столбцами,содержат эти три цифры.

Выбор из двойного полезен для запуска функций.Функция может быть запущена с ручным вводом вместо выбора чего-либо другого в ней.Например:

select some_func('First Parameter', 'Second parameter') from dual;

вернет результаты some_func.

...