J'aimerais utiliser la fonction de série Generate dans Redshift, mais n'a pas réussi.
La documentation redshift dit qu'il n'est pas pris en charge. Le code suivant fonctionne:
select *
from generate_series(1,10,1)
les sorties:
1
2
3
...
10
Je voudrais faire la même chose avec les dates. J'ai essayé un certain nombre de variations, notamment:
select *
from generate_series(date('2008-10-01'),date('2008-10-10 00:00:00'),1)
démunie:
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]
Aussi essayé:
select *
from generate_series('2008-10-01 00:00:00'::timestamp,
'2008-10-10 00:00:00'::timestamp,'1 day')
Et essayé:
select *
from generate_series(cast('2008-10-01 00:00:00' as datetime),
cast('2008-10-10 00:00:00' as datetime),'1 day')
les deux lancent:
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]
Sinon on dirait que je vais utiliser ce code d'un autre poste:
SELECT to_char(DATE '2008-01-01'
+ (interval '1 month' * generate_series(0,57)), 'YYYY-MM-DD') AS ym
PostgreSQL Generate_series () avec fonction SQL comme arguments
Amazon Redshift semble être basé sur PostgreSQL 8.0.2 . Les arguments de l'horodatage pour générer des_series () ont été ajoutés en 8.4.
Quelque chose comme ça, qui évite ce problème, pourrait Travailler dans Redshift.
SELECT current_date + (n || ' days')::interval
from generate_series (1, 30) n
Cela fonctionne dans PostgreSQL 8.3, qui est la version la plus ancienne que je puisse tester. Il est documenté dans 8.0.26.
plus tard. . .
Il semble que générate_series () n'est pas pris en charge dans Redshift. Mais étant donné que vous avez vérifié que select * from generate_series(1,10,1)
le fait Travail, la syntaxe ci-dessus vous donne au moins une chance de combattre. (Bien que le type de données d'intervalle soit également documenté comme non pris en charge sur Redshift.)
encore plus tard. . .
Vous pouvez également créer une table d'entiers.
create table integers (
n integer primary key
);
Peuplez-le cependant que vous aimez. Vous pourrez peut-être utiliser Generate_Series () localement, vider la table et le charger sur RedShift. (Je ne sais pas; Je n'utilise pas Redshift.)
Quoi qu'il en soit, vous pouvez faire une date simple par rapport à cette table sans se référer directement à Generate_series () ou aux types de données d'intervalle.
select (current_date + n)
from integers
where n < 31;
Cela fonctionne dans 8.3, au moins.
En utilisant RedShift aujourd'hui, vous pouvez générer une gamme de dates à l'aide de fonctions DateTime et d'alimentation dans une table numérique.
select (getdate()::date - generate_series)::date from generate_series(1,30,1)
Génère ceci pour moi
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
La fonction generate_series()
n'est pas entièrement prise en charge par RedShift. Voir le (((( Fonctions PostgreSQL non prises Section du Guide du développeur.
[~ # ~ ~] Mise à jour [~ # ~]
generate_series travaille avec Redshift maintenant.
SELECT CURRENT_DATE::TIMESTAMP - (i * interval '1 day') as date_datetime
FROM generate_series(1,31) i
ORDER BY 1
Cela générera une date de 30 jours
Je devais faire quelque chose de similaire, mais avec des intervalles de 5 minutes sur 7 jours. Alors voici un piratage basé sur CTE (laid mais pas trop verbeux)
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
Devrait être capable de l'étendre à d'autres régimes de génération. L'astuce ici utilise la jointure du produit cartésien (c'est-à-dire aucune clause de jointure/où) pour multiplier les CTE fabriqués à la main pour produire les augmentations nécessaires et s'appliquer à une date d'ancrage.
Pour les commentaires de @ ryan Tuck et @ slobodan pejicgenerate_series()
ne fonctionne pas sur Redshift lors de la jonction à une autre table.
La solution que j'ai utilisée était d'écrire chaque valeur de la série de la requête:
SELECT
'2019-01-01'::date AS date_month
UNION ALL
SELECT
'2019-02-01'::date AS date_month
Utilisation d'un Python fonction comme ceci:
import arrow
def generate_date_series(start, end):
start = arrow.get(start)
end = arrow.get(end)
months = list(
f"SELECT '{month.format('YYYY-MM-DD')}'::date AS date_month"
for month in arrow.Arrow.range('month', start, end)
)
return "\nUNION ALL\n".join(months)