2010-02-19 6 views
5

Может ли любой из этих запросов быть выполнен в SQL?SELECT any FROM system

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, и именно поэтому я спрашиваю.

+4

Непонятно, что вы просите. В чем проблема, с которой вы сталкиваетесь? Вы спрашиваете, можете ли вы запросить все таблицы во всех базах данных или спросите, можете ли вы запросить таблицу с именем «система»? Второй пример должен работать нормально. Первый пример не будет работать, как вы думаете, это два фрагмента текста, а не даты. Вам нужно будет хранить даты в правильном формате. – Tom

+1

Я думаю, что они означают простые запросы для получения списков дат или цифр между заданными диапазонами, на лету. – MartW

+2

@Tom: Я предполагаю, что он запрашивает 'generate_series'. – Quassnoi

ответ

12

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

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

Извините.

+0

ах. вы избили меня до этого ... очень хороший ответ +1 – EvilTeach

+0

MYSQL: 'SELECT num from (выберите @num: = @ num + 1 как num из big_table, (выберите @num: = 10) num) как q WHERE num <= 19' (http://stackoverflow.com/a/6871220/2115135) –

+0

@JakubKania: сначала нужно иметь 'big_table'. – Quassnoi

0

Не уверен, если это то, что вы , но если вы хотите выбрать что-то не из таблицы, вы можете использовать «DUAL»

select 1, 2, 3 from dual; 

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

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

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

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

0

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

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

+0

Можно ли это использовать иначе, чем в предложении where? Или можно использовать предложение where, кроме выбора из таблицы? –

+0

Просто нужно помнить, что BETWEEN включает ограничения, в то время как пример OP исключает их. – DyingCactus

0

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

+0

Вы можете. Но AFAIK, 'WHERE' должны использоваться при выборе из таблицы или вида. Кажется, возникает вопрос, как создавать даты или числа, т. Е. НЕ из таблицы или представления, которые уже заполнены. –

+0

Что такое 'И WHERE'? –

1

В 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

Если вы хотите получить список дней, с 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 

Заметки о производительности

Тестирование его here, производительность на удивление хорошо: выше запрос занимает 0,0009 сек.

Если мы расширим подзапрос, чтобы сгенерировать ок. 100 000 номеров (и, следовательно, даты на 274 года), она работает в 0,0458 сек.

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

+0

Я предпочел бы использовать функцию DATE FUNCTION MVJ, которая намного более гибкая, а производительность фантастическая. http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=61519 – JonH

+0

Это не доступно в MySQL и в Postgresql и SQLite – Pentium10

0

Простейшим решением этой проблемы является таблица 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 занимает около 434 тысяч строк. Вероятно, вам это не понадобится, но даже если вы это сделаете, хранилище будет крошечным.

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

Select NumericValue 
From dbo.Tally 
    Left Join MyTable 
     On Tally.NumericValue = MyTable.IdentityColumn 
Where Tally.NumericValue Between SomeLowValue And SomeHighValue 
Смежные вопросы