ВЫБЕРИТЕ любую ИЗ системы

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


person Community    schedule 19.02.2010    source источник
comment
Не понятно, о чем вы спрашиваете. В чем проблема? Вы спрашиваете, можете ли вы запрашивать все таблицы во всех базах данных, или вы спрашиваете, можете ли вы запрашивать таблицу с именем system? Второй пример должен работать нормально. Первый пример не будет работать, как вы думаете, это два фрагмента текста, а не даты. Вам нужно будет хранить даты в правильном формате.   -  person Tom    schedule 19.02.2010
comment
Я думаю, что они означают простые запросы для получения списков дат или чисел между заданными диапазонами на лету.   -  person MartW    schedule 19.02.2010
comment
@Tom: я предполагаю, что он просит generate_series.   -  person Quassnoi    schedule 19.02.2010
comment
Какие dbms вы используете?   -  person David Oneill    schedule 19.02.2010
comment
Почему вы делаете это в БД? Это похоже на то, что логический уровень должен делать.   -  person rossipedia    schedule 19.02.2010
comment
@Bryan Ross, мне нужно было сделать что-то в этом роде, когда я передавал даты в функцию базы данных, а простая МЕЖДУ датой1 и датой2 не работала.   -  person Nathan Koop    schedule 19.02.2010


Ответы (8)


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

In PostgreSQL:

SELECT  num
FROM    generate_series (11, 19) num

In 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

In MySQL:

Прости.

person Quassnoi    schedule 19.02.2010
comment
ах. ты меня опередил... очень хороший ответ +1 - person EvilTeach; 19.02.2010
comment
MYSQL: SELECT num from (select @num:=@num+1 as num from big_table, (select @num:=10) num) as q WHERE num<=19 (stackoverflow.com/a/6871220/2115135) - person Jakub Kania; 05.03.2013
comment
@JakubKania: сначала нужно иметь big_table. - person Quassnoi; 05.03.2013
comment
@Quassnoi, вам нужна любая таблица как минимум с двумя строками, и оттуда вы можете выполнить перекрестное соединение. Наличие big_table не является проблемой, проблема в том, что вам может понадобиться еще одно перекрестное соединение, если набор записей слишком велик. - person Jakub Kania; 05.03.2013
comment
@JakubKania: у вас может не быть прав на запись в базу данных, как это обычно бывает с разработчиками отчетов. В этом случае вам может сойти с рук (SELECT 1 UNION ALL SELECT 2 …) q, но точный макет запроса будет зависеть от количества нужных вам записей. Я прекрасно знаю обходные пути, вопрос не о них. - person Quassnoi; 05.03.2013

Что-то вроде свиданий... У Майкла Валентайна Джонса из команды SQL есть ПОТРЯСАЮЩАЯ функция свиданий.

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

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

person JonH    schedule 19.02.2010

В Оракуле

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
)
person EvilTeach    schedule 19.02.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 с.

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

person Pentium10    schedule 19.02.2010
comment
Я бы предпочел использовать функцию DATE FUNCTION от MVJ, она гораздо более гибкая, а производительность просто фантастическая. sqlteam.com/forums/topic.asp?TOPIC_ID=61519 - person JonH; 19.02.2010
comment
Этого нет ни в MySQL, ни в Postgresql, ни в SQLite. - person Pentium10; 19.02.2010

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

select 1, 2, 3 from dual;

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

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

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

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

person David Oneill    schedule 19.02.2010

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

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

person ZippyV    schedule 19.02.2010
comment
Можно ли использовать это иначе, чем в предложении where? Или можно ли использовать предложение where, кроме выбора из таблицы? - person David Oneill; 19.02.2010
comment
Просто нужно помнить, что BETWEEN включает границы, а пример OP их исключает. - person ; 19.02.2010

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

person Eric    schedule 19.02.2010
comment
Ты сможешь. Но, насколько мне известно, WHERE необходимо использовать при выборе из таблицы или представления. Кажется, вопрос заключается в том, как генерировать даты или числа, т.е. НЕ из таблицы или представления, которые уже заполнены. - person David Oneill; 19.02.2010

Самым простым решением этой проблемы является таблица 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 

Once you have that table populated, you never need touch it unless you want to expand it. I combined the dates and numbers into a single table but if you needed more numbers than dates, then you could break it into two tables. In addition, I arbitrarily filled the table with 100K rows but you could obviously add more. Every day between 1900-01-01 to 9999-12-31 takes about 434K rows. You probably won't need that many but even if you did, the storage is tiny.

Regardless, this is a common technique to solving many gaps and sequences problems. For example, your original queries all ran in less than tenth of a second. You can also use this sort of table to solve gaps problems like:

Select NumericValue
From dbo.Tally
    Left Join MyTable
        On Tally.NumericValue = MyTable.IdentityColumn
Where Tally.NumericValue Between SomeLowValue And SomeHighValue
person Community    schedule 20.02.2010