Supposons que j'ai le tableau suivant et que je cherche à extraire le nombre de jours entre chaque mouvement positif et négatif. De cette façon, pour chaque 'id', je dois calculer les jours intermédiaires entre chaque paire de dates et la proportion du mouvement négatif sur le positif, en SQL Teradata.
id date money ---------------- 1 1-1 10 1 3-1 -5 1 9-1 8 1 10-1 -2 2 3-1 10 2 9-1 -10 2 15-1 20 2 19-1 -15 id days_in prop ----------------- 1 2 0.5 1 1 0.25 2 6 1 2 4 0.75
3 Réponses :
Vous voulez quelque chose comme ceci:
select A.id, B.date - A.date as "days_in", (B.money - A.money) / (b.date - A.date) as "prop" from ( select X.id, X.date, min(NextDate.date) as "MinNextDate", X.money from [yourTable] X, [yourtable] NextDate where NextDate.date > X.date and NextDate.id = X.id ) A, [YourTable] B where A.id = B.id and B.date = A.MinNextDate
Je pense que teradata renvoie une différence de date sous forme de nombre de jours au format entier. S'il s'agit d'une date / heure, vous devrez peut-être mettre les valeurs de date / heure en dates avant de soustraire.
Il manque un GROUP BY dans la table dérivée. Et selon le nombre de lignes par identifiant, cela peut nécessiter beaucoup de CPU en raison de la non-équi-jointure.
Que diriez-vous d'utiliser une auto-jointure d'une manière légèrement différente, mais elle produira toujours des lignes supplémentaires puisque la jointure sera effectuée avec chaque ligne .. vous pouvez la restreindre davantage en fonction de vos critères
select a.id, (b.date-a.date) as days_in, abs(b.money)/a.money as prop from <table> a inner join <table> b on a.id=b.id and a.date<>b.date where (b.date-a.date)>0 and (abs(b.money)/a.money)>0 and (a.money>0 and b.money<=-1)
Pour obtenir la valeur positive précédente, vous pouvez utiliser last_value
:
SELECT id ,datecol -- ratio between current negative and previous positive money ,Abs(Cast(money AS NUMBER)) / Last_Value(CASE WHEN money > 0 THEN money end IGNORE NULLS) Over (PARTITION BY id ORDER BY datecol) -- difference between current and previous date -- might need a cast to date or interval result if the datecol is a Timestamp ,datecol- Last_Value(CASE WHEN money > 0 THEN DATE_ end IGNORE NULLS) Over (PARTITION BY id ORDER BY datecol) FROM vt AS t -- return only rows with negative money QUALIFY money < 0
Bien sûr, cela suppose qu'il y a toujours des lignes alternées avec des valeurs positives et négatives.
Puissiez-vous faire une auto-adhésion et vérifier la différence. Ne pas obtenir exactement ce dont vous avez besoin. Vous devrez peut-être mieux expliquer le problème / la sortie nécessaire. Ajoutez un nom (tableaux A et B) aux données que vous avez dans votre question.
Quel type de données de colonne utilisez-vous pour la colonne de date? Il semble que cela puisse être une chaîne, mais est-ce vraiment une vraie date / heure?
Oui, ce serait un vrai datetime.
Que faire s'il y a plusieurs lignes consécutives avec des valeurs positives ou négatives? Et s'il y a deux lignes avec la même date?