2013-06-24 15 views
12

Ich würde gerne die Generate-Serie-Funktion in Rotverschiebung, aber waren nicht erfolgreich.Verwendung der SQL-Funktion generate_series() in Rotverschiebung

Die Redshift-Dokumentation besagt, dass sie nicht unterstützt wird. Der folgende Code funktioniert:

select * 
from generate_series(1,10,1) 

Ausgänge:

1 
2 
3 
... 
10 

Ich mag würde das gleiche mit Daten zu tun. Ich habe eine Reihe von Variationen ausprobiert, darunter:

select * 
from generate_series(date('2008-10-01'),date('2008-10-10 00:00:00'),1) 

Kicks aus:

ERROR: function generate_series(date, date, integer) does not exist 
Hint: No function matches the given name and argument types. 
You may need to add explicit type casts. [SQL State=42883] 

auch versucht:

select * 
from generate_series('2008-10-01 00:00:00'::timestamp, 
'2008-10-10 00:00:00'::timestamp,'1 day') 

Und versucht:

select * 
from generate_series(cast('2008-10-01 00:00:00' as datetime), 
cast('2008-10-10 00:00:00' as datetime),'1 day') 

beiden Kicks aus:

ERROR: function generate_series(timestamp without time zone, timestamp without time zone, "unknown") does not exist 
Hint: No function matches the given name and argument types. 
You may need to add explicit type casts. [SQL State=42883] 

Wenn sieht nicht, wie ich diesen Code aus einem anderen Beitrag verwenden werden:

SELECT to_char(DATE '2008-01-01' 
+ (interval '1 month' * generate_series(0,57)), 'YYYY-MM-DD') AS ym 

PostgreSQL generate_series() with SQL function as arguments

+2

Führen Sie 'SELECT version()' für Ihre Datenbank aus, um Ihre Version von Postgres abzurufen. –

+0

Für eine Problemumgehung finden Sie unter: http://Stackoverflow.com/a/34167753/3019685 – systemjack

+0

Ich habe eine Problemumgehung in einer ähnlichen Frage hier https://StackOverflow.com/Questions/22759980/generate-series-method-fails- in-redshift – AlexYes

Antwort

15

Amazon Redshift seems to be based on PostgreSQL 8.0.2. Die Timestamp-Argumente für generate_series() wurden in 8.4 hinzugefügt.

So etwas, das dieses Problem umgeht, könnte arbeiten in Redshift.

SELECT current_date + (n || ' days')::interval 
from generate_series (1, 30) n 

Es funktioniert in PostgreSQL 8.3, das ist die früheste Version, die ich testen kann. Es ist in 8.0.26 dokumentiert.

Später. . .

Es scheint, dass generate_series() is unsupported in Redshift. Aber vorausgesetzt, dass Sie verifiziert haben, dass select * from generate_series(1,10,1)funktioniert funktioniert, die Syntax oben gibt Ihnen zumindest eine Chance zu kämpfen. (Obwohl der Intervall-Datentyp auch bei Redshift nicht unterstützt wird.)

Noch später. . .

Sie können auch eine Tabelle mit Ganzzahlen erstellen.

create table integers (
    n integer primary key 
); 

Befüllen Sie es, wie Sie möchten. Sie können möglicherweise generate_series() lokal verwenden, die Tabelle ausgeben und auf Redshift laden. (Ich weiß es nicht; ich verwende Redshift nicht.)

Wie auch immer, Sie können einfache Datumsarithmetik mit dieser Tabelle durchführen, ohne direkt auf generate_series() oder auf Intervalldatentypen zu verweisen.

select (current_date + n) 
from integers 
where n < 31; 

Das funktioniert in mindestens 8.3.

+3

+1 Das scheint es zu erklären. Weniger als beeindruckend von Amazon ... –

7

Mit Redshift können Sie heute eine Reihe von Datumsangaben generieren, indem Sie datetime-Funktionen verwenden und eine Zahlentabelle einspeisen.

select (getdate()::date - generate_series)::date from generate_series(1,30,1) 

Erzeugt das für mich

date 
2015-11-06 
2015-11-05 
2015-11-04 
2015-11-03 
2015-11-02 
2015-11-01 
2015-10-31 
2015-10-30 
2015-10-29 
2015-10-28 
2015-10-27 
2015-10-26 
2015-10-25 
2015-10-24 
2015-10-23 
2015-10-22 
2015-10-21 
2015-10-20 
2015-10-19 
2015-10-18 
2015-10-17 
2015-10-16 
2015-10-15 
2015-10-14 
2015-10-13 
2015-10-12 
2015-10-11 
2015-10-10 
2015-10-09 
2015-10-08 
+2

während dies eine Reihe generiert, habe ich keine Möglichkeit gefunden (CTE, Unterabfrage oder Einfügen in eine Tabelle oder temporäre Tabelle, um es zu einer anderen Tabelle zum Filtern beizutreten). – cfeduke

+1

@cfeduke Sie könnten dies in eine temporäre Tabelle als '' 'mit Serie AS ( wählen Sie * von generate_series (1,10,1) ) wähle * aus der Serie' '' – blotto

+1

@blotto - danke! Dein Kommentar und das letzte Beispiel in der Frage haben das Problem für mich gelöst. – GeekyDeaks

0

Ich brauchte etwas Ähnliches zu tun, jedoch mit 5-Minuten-Intervallen über 7 Tage. Also hier ist ein CTE basierte Hack (hässlich, aber nicht zu ausführlich)

INSERT INTO five_min_periods 
WITH 
periods AS (select 0 as num UNION select 1 as num UNION select 2 UNION select 3 UNION select 4 UNION select 5 UNION select 6 UNION select 7 UNION select 8 UNION select 9 UNION select 10 UNION select 11), 
hours AS (select num from periods UNION ALL select num + 12 from periods), 
days  AS (select num from periods where num <= 6), 
rightnow AS (select CAST(TO_CHAR(GETDATE(), 'yyyy-mm-dd hh24') || ':' || trim(TO_CHAR((ROUND((DATEPART (MINUTE, GETDATE())/5), 1) * 5),'09')) AS TIMESTAMP) as start) 
select 
    ROW_NUMBER() OVER(ORDER BY d.num DESC, h.num DESC, p.num DESC) as idx 
    , DATEADD(minutes, -p.num * 5, DATEADD(hours, -h.num, DATEADD(days, -d.num, n.start))) AS period_date 
from days d, hours h, periods p, rightnow n 

sollten in der Lage sein, dies zu anderen Generation Systeme zu erweitern. Der Trick besteht darin, den kartesischen Produktjoin (d. H. Keine JOIN/WHERE-Klausel) zu verwenden, um die handgefertigten CTEs zu multiplizieren, um die notwendigen Inkremente zu erzeugen und auf ein Ankerdatum anzuwenden.

Verwandte Themen