2010-02-19 13 views
5

Czy którekolwiek z tych zapytań można wykonać w SQL?WYBIERZ dowolne z systemu

SELECT dates FROM system 
WHERE dates > 'January 5, 2010' AND dates < 'January 30, 2010' 

SELECT number FROM system 
WHERE number > 10 AND number < 20 

Chciałbym stworzyć generate_series i dlatego pytam.

+4

Nie jest jasne, o co pytasz. Jaki masz problem? Czy pytasz, czy możesz wysłać zapytanie do wszystkich tabel we wszystkich bazach danych, czy pytasz, czy możesz zapytać o tabelę o nazwie "system"? Drugi przykład powinien działać dobrze. Pierwszy przykład nie będzie działał tak, jak myślisz, są to dwa fragmenty tekstu, a nie daty. Będziesz musiał przechowywać daty we właściwym formacie. – Tom

+1

Sądzę, że mają na myśli proste zapytania, aby w dowolnym momencie uzyskać listy dat lub liczb między podanymi zakresami. – MartW

+2

@ Tom: Zakładam, że pyta o 'generate_series'. – Quassnoi

Odpowiedz

12

Zakładam, że chcesz wygenerować zestaw rekordów o dowolnej liczbie wartości, w oparciu o pierwszą i ostatnią wartość w serii.

W PostgreSQL:

SELECT num 
FROM generate_series (11, 19) num 

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

W Oracle:

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

W MySQL:

Przepraszamy.

+0

ah. pokonałeś mnie ... bardzo dobra odpowiedź +1 – EvilTeach

+0

MYSQL: 'WYBIERZ num od (wybierz @ num: = @ num + 1 jako num od big_table, (wybierz @ num: = 10) num) jako q WHERE num <= 19' (http://stackoverflow.com/a/6871220/2115135) –

+0

@JakubKania: najpierw musisz mieć 'big_table'. – Quassnoi

0

Nie wiem, czy to jest to, czego "Pytam, ale jeśli chcesz wybrać coś nie ze stołu, możesz użyć" DUAL "

select 1, 2, 3 from dual; 

zwróci wiersz z 3 kolumnami, zawierający te trzy cyfry.

Wybór z podwójnego jest przydatny do uruchamiania funkcji. Funkcję można uruchamiać z ręcznym wprowadzaniem zamiast wybierać w niej coś innego. Na przykład:

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

zwróci wyniki some_func.

0

Można wybrać zakres używając WHERE i AND WHERE. Nie mogę mówić do występu, ale jest to możliwe.

+0

Możesz. Ale AFAIK, "GDZIE" musi być używany podczas wybierania z tabeli lub widoku. Pytanie wydaje się pytać, jak generować daty lub liczby, tj. NIE z tabeli lub widoku, które już są wypełnione. –

+0

Co to jest "AND WHERE"? –

1

W 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

Jeśli chcesz otrzymać listę dni, a SQL jak

wybrać ...w dniach, w których date jest pomiędzy '2010-01-20 2010-01-24' i ''

i powrotnego danych, takie jak:

days 
---------- 
2010-01-20 
2010-01-21 
2010-01-22 
2010-01-23 
2010-01-24 

Rozwiązanie to nie wykorzystuje pętle, procedury lub tabele Temp. Podzapytanie generuje daty z ostatnich tysiąc dni i może zostać przedłużone tak, aby przejść tak daleko w tył lub do przodu, jak chcesz.

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' 

wyjściowa:

Date 
---------- 
2010-01-24 
2010-01-23 
2010-01-22 
2010-01-21 
2010-01-20 

Uwagi dotyczące wydajności

Testowanie go here, wydajność jest zaskakująco dobre: ​​powyższe zapytanie trwa 0,0009 sek.

Jeśli rozszerzymy podzapytanie, aby wygenerować około. 100 000 liczb (a więc około 274 lat dat), trwa to 0,0458 sek.

Nawiasem mówiąc, jest to bardzo przenośna technika, która działa z większością baz danych z drobnymi korektami.

+0

Wolałbym używać DATE FUNCTION MVJ jest znacznie bardziej elastyczny, a wydajność jest fantastyczna. http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=61519 – JonH

+0

To nie jest dostępne w MySQL ani w Postgresql i SQLite – Pentium10

0

Najprostszym rozwiązaniem tego problemu jest tabela Tally lub Numbers. To jest stół, który po prostu przechowuje ciąg liczb i/lub daty

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

Kiedy już, że tabela wypełniana, nigdy nie trzeba go dotknąć, jeśli nie chcesz, aby go rozwinąć. Połączyłem daty i liczby w jeden stół, ale jeśli potrzebowałeś więcej liczb niż dat, możesz podzielić je na dwie tabele. Dodatkowo arbitralnie wypełniłem tabelę 100-krotnym rzędem, ale można oczywiście dodać więcej. Codziennie od 1900-01-01 do 9999-12-31 trwa około 434 tysięcy wierszy. Prawdopodobnie nie będziesz potrzebował aż tylu, ale nawet jeśli tak, to miejsce jest małe.

Bez względu na to, jest to powszechna technika rozwiązywania wielu problemów z przerwami i sekwencjami. Na przykład wszystkie Twoje pierwotne zapytania trwały mniej niż jedną dziesiątą sekundy. Możesz również użyć tego rodzaju tabeli do rozwiązywania problemów z lukami, takich jak:

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