J'ai essayé désespérément d'obtenir l'instruction SQL suivante pour renvoyer les résultats de la requête et la valeur par défaut à 0 s'il n'y a pas de lignes correspondant à la requête.
Voici le résultat attendu:
select coalesce(vol,0) as vol, year from (select sum(vol) as vol, year from schema.fact_data join schema.period_data on schema.fact_data.period_tag = schema.period_data.tag join schema.product_data on schema.fact_data.product_tag = schema.product_data.tag join schema.market_data on schema.fact_data.market_tag = schema.market_data.tag where "retailer"='MadeUpRetailer' and "product_tag"='FakeProductTag' and "year"='2018' group by year ) as DerivedTable;
Au lieu de cela, j'obtiens:
vol | year -----+------ (0 rows)
Voici l'instruction sql:
vol | year -------+------ 0 | 2018
Je connais le La requête fonctionne car elle renvoie des données lorsqu'il y a des données. N'a pas la valeur par défaut à 0 comme prévu ...
Toute aide pour trouver pourquoi c'est le cas serait très appréciée!
3 Réponses :
En utilisant votre sous-requête DerivedTable
, vous pouvez écrire:
SELECT coalesce(DerivedTable.vol, 0) AS vol, y.year FROM (VALUES ('2018'::text)) AS y(year) LEFT JOIN (SELECT ...) AS DerivedTable ON DerivedTable.year = y.year;
Mais cela ne fonctionnera que pour l'année 2018. Correct? Je pense que 2018 était un exemple.
Eh bien, il y avait 2018
dans la requête de la question. Ce n'est pas un problème d'utiliser un paramètre à cet endroit.
@Neptune: si vous voulez faire cela pendant une plage d'années (par exemple, de 2000
à 2018
), remplacez VALUES ('2018' :: text )
avec SELECT generate_series (2000, 2018) :: text
.
@LaurenzAlbe merci pour votre réponse! Je n'arrive pas à faire fonctionner cet extrait de code, que remplaceriez-vous exactement ... par mon exemple?
Si vous remplacez le ...
dans ma requête par votre sous-requête, vous obtenez le résultat souhaité, non? Si non, veuillez me dire l'erreur (je ne l'ai pas testée). Si oui, veuillez expliquer votre problème plus en détail.
Voici l'erreur que j'obtiens: ERROR: erreur de syntaxe à ou près de "y" LINE 2: y.year
Zounds! J'ai oublié une virgule à la fin de la première ligne. Pardon.
D'après le code que vous avez publié, il n'est pas clair dans quel tableau vous avez la colonne année
.
Vous pouvez utiliser UNION pour récupérer une seule ligne au cas où il n'y aurait pas de lignes dans ce tableau pour l'année 2018 comme ceci:
select sum(vol) as vol, year from schema.fact_data innrt join schema.period_data on schema.fact_data.period_tag = schema.period_data.tag inner join schema.product_data on schema.fact_data.product_tag = schema.product_data.tag inner join schema.market_data on schema.fact_data.market_tag = schema.market_data.tag where "retailer"='MadeUpRetailer' and "product_tag"='FakeProductTag' and "year"='2018' group by "year" union select 0 as vol, '2018' as year where not exists ( select 1 from tablename where "year" = '2018' )
S'il y a des lignes pour l'année 2018, rien ne sera récupéré par la deuxième requête,
Supprimez le GROUP BY
(et la requête externe):
select v.yyyy as year, coalesce(sum(vol), 0) as vol from (values (2018), (2019)) v(yyyy) left join schema.fact_data f on f.year = v.yyyy left join -- this is just an example. I have no idea where year is coming from schema.period_data p on f.period_tag = p.tag left join schema.product_data pr on f.product_tag = pr.tag left join schema.market_data m on fd.market_tag = m.tag group by v.yyyy
Une requête d'agrégation sans GROUP BY
renvoie toujours exactement un ligne, donc cela devrait faire ce que vous voulez.
EDIT:
La requête ressemblerait à quelque chose comme ceci:
select 2018 as year, coalesce(sum(vol), 0) as vol from schema.fact_data f join schema.period_data p on f.period_tag = p.tag join schema.product_data pr on f.product_tag = pr.tag join schema.market_data m on fd.market_tag = m.tag where "retailer" = 'MadeUpRetailer' and "product_tag" = 'FakeProductTag' and "year" = '2018';
Cependant , vous devez déplacer les conditions where
vers les clauses on
appropriées. Je n'ai aucune idée d'où viennent les colonnes.
Cette requête retourne bien une ligne, mais alors la colonne 2018 est toujours vide ce qui n'est pas le comportement souhaité
@ludo. . . Si vous voulez 0
au lieu de NULL
, utilisez simplement coalesce ()
.
Merci pour ce @GordonLinoff. J'obtiens le résultat souhaité! Cependant, j'ai besoin que les résultats soient regroupés par année. Donc, si je mets where year in (2018,2019)
, la requête se groupera sur l'année et renverra deux lignes, que les lignes contiennent des données ou non. Avez-vous une idée de comment je pourrais faire cela?
Veuillez qualifier tous vos noms de colonnes.