J'ai donc reçu une demande de données de la part d'un membre de mon entreprise. Cette demande de données nécessite une requête SQL de plusieurs colonnes à partir de plusieurs tables MAIS ne peut être que l'incident le plus récent d'une colonne d'une de ces tables. Voici le kicker ... chaque table a une seule colonne qu'elle partage avec une autre table. Donc, pour obtenir ce "rapport", je dois le faire morceau par morceau.
Voici à quoi ressemblait ma requête initiale avant de réaliser que je n'ai besoin que de la mise à jour la plus récente de l'une des tables:
Description|Price |ID |DescriptionB |date |DescriptionC --------------------------------------------------------------------- Computer |300 |554 |7% Off |9/1/2019 |Includes CPU Computer |300 |554 |7% Off |9/1/2019 |Includes DOG Computer |300 |554 |7% Off |9/1/2019 |Includes CAT Printer |75 |801 |1% Off |1/3/2019 |Includes DOS Printer |75 |801 |1% Off |1/3/2019 |Includes PIG Printer |75 |801 |1% Off |1/3/2019 |Includes RAT
J'ai réalisé que le "c.date" ci-dessus n'a besoin d'afficher que la date la plus récente pour chaque ID / DescriptionC unique.
Voici un exemple de résultat de la requête initiale:
Description|Price |ID |DescriptionB |date |DescriptionC --------------------------------------------------------------------- Computer |300 |554 |7% Off |9/1/2019 |Includes CAT
Voici le résultat de la requête de Laurenz ci-dessous:
Description|Price |ID |DescriptionB |date |DescriptionC --------------------------------------------------------------------- Computer |300 |554 |5% Off |3/2/2010 |Includes CPU Computer |300 |554 |5% Off |3/2/2010 |Includes DOG Computer |300 |554 |5% Off |3/2/2010 |Includes CAT Computer |300 |554 |9% Off |4/3/2011 |Includes CPU Computer |300 |554 |9% Off |4/3/2011 |Includes DOG Computer |300 |554 |9% Off |4/3/2011 |Includes CAT Computer |300 |554 |7% Off |9/1/2019 |Includes CPU Computer |300 |554 |7% Off |9/1/2019 |Includes DOG Computer |300 |554 |7% Off |9/1/2019 |Includes CAT Printer |75 |801 |3% Off |6/3/2012 |Includes DOS Printer |75 |801 |3% Off |6/3/2012 |Includes PIG Printer |75 |801 |3% Off |6/3/2012 |Includes RAT Printer |75 |801 |9% Off |8/3/2013 |Includes DOS Printer |75 |801 |9% Off |8/3/2013 |Includes PIG Printer |75 |801 |9% Off |8/3/2013 |Includes RAT Printer |75 |801 |1% Off |1/3/2019 |Includes DOS Printer |75 |801 |1% Off |1/3/2019 |Includes PIG Printer |75 |801 |1% Off |1/3/2019 |Includes RAT
... proche mais pas encore tout à fait là.
Résultat souhaité:
SELECT a.description AS "Description", a.pricing AS "Price", b.id AS "ID", c.descriptionb AS "DescriptionB", c.date AS "date", d.descriptionc AS "DescriptionC" FROM database.table1 a, database.table2 b, database.table3 c, database.table4 d WHERE a.description = b.descriptive_info AND b.id = c.comp_id AND c.descriptionb = d.long_description AND d.id_for_a = a.id AND a.company IN ( '000', '001', '002', '003', '004' ) AND b.expdate >= Now()
Comme vous pouvez le voir, il y en a plusieurs les dates pour le «même produit», les produits en double avec des descriptions variables, etc. Je ne veux essentiellement que les lignes avec la «date» la plus récente pour chaque ID / DescriptionC unique. J'espère que c'est un peu plus facile à comprendre que mon article d'origine.
BTW, ce sont des exemples simplifiés car je ne veux pas avoir d'ennuis avec mon entreprise, mais la requête et les concepts sont les mêmes. Si vous pouvez imaginer plusieurs produits avec de nombreuses instances de chaque produit plusieurs fois, vous pouvez imaginer la taille de l'ensemble de données. Je ne me soucie que de l'instance la plus récente de chaque ID / DescriptionC unique.
3 Réponses :
Je comprends que, parmi les résultats de la requête actuelle, vous voulez simplement sélectionner celui qui a la valeur maximale sur c.date
.
Une solution serait de transformer la requête existante en sous-requête, et d'utiliser ROW_NUMBER ()
pour classer les enregistrements en descendant c.date
. Ensuite, la requête externe peut simplement filtrer sur l'enregistrement le mieux classé.
Requête:
SELECT * FROM ( SELECT a.description AS "Description", a.pricing AS "Price", b.string AS "String", c.description AS "Description", c.date AS "date", d.descriptionb AS "DescriptionB", ROW_NUMBER() OVER (ORDER BY c.date DESC) AS rn FROM database.table1 a INNER JOIN database.table2 b ON a.id = b.table1_id INNER JOIN database.table3 c ON b.element = c.table2_element AND b.expdate >= Now() INNER JOIN database.table4 d ON c.value = d.table3_value WHERE a.company IN ( '000', '001', '002', '003', '004' ) ) x WHERE rn = 1;
PS:
préfère toujours les jointures explicites au lieu des jointures implicites à l'ancienne; J'ai modifié la requête initiale en conséquence
si vous avez besoin de la date maximum par partition (ce qui n'est pas évident à dire sans voir des exemples de données), il vous suffit d'ajouter une clause PARTITION BY
au ROW_NUMBER ()
fonction.
Génial, cela a supprimé l'erreur, cependant, maintenant il n'aime pas l'avant-dernière clause "WHERE": ERROR: erreur de syntaxe à ou près de "WHERE" Voici un extrait de la requête ACTUAL beaucoup plus grande tout ce qui entoure "WHERE "instruction: INNER JOIN viper_logical_1.promotion_relatedmarketitems i ON i.element = b.externalid WHERE a.externalid IN ('5957962', '2882541')) x WHERE rn = 1 LINE 35: WHERE
@ user2079024: eh bien, il est difficile de dire ce qui ne va pas dans votre requête réelle ... Une chose que vous pouvez faire est d’essayer de limiter le problème: lancez d’abord la sous-requête et voyez si cela fonctionne, puis exécutez toute la requête.
D'accord ... donc cette requête est proche mais pas encore tout à fait là. J'ai mis à jour ma description originale du problème, les résultats et les résultats souhaités. J'espère que cela rendra les choses un peu plus claires quant à ce que je tente d'accomplir. Encore une fois, toute aide supplémentaire serait grandement appréciée!
Le sql suivant peut être utilisé pour résoudre la question:
SELECT * FROM ( SELECT a.description AS "Description", a.pricing AS "Price", b.string AS "String", c.description AS "Description", c.date AS "date", d.descriptionb AS "DescriptionB", ROW_NUMBER() OVER (ORDER BY c.date DESC PARTITION BY B.ID ) AS rn FROM database.table1 a INNER JOIN database.table2 b ON a.id = b.table1_id INNER JOIN database.table3 c ON b.element = c.table2_element AND b.expdate >= Now() INNER JOIN database.table4 d ON c.value = d.table3_value WHERE a.company IN ( '000', '001', '002', '003', '004' ) ) x WHERE rn = 1;
Merci beaucoup à tous. La réponse de Hal McGee était fondamentalement correcte! J'ai juste dû peaufiner certaines choses. Voici un exemple de la requête complète que j'ai fini par utiliser et qui fonctionnait car j'en avais besoin pour:
SELECT * FROM ( SELECT a.description AS "Description", a.pricing AS "Price", b.string AS "String", c.description AS "Description", c.date AS "date", d.descriptionb AS "DescriptionB", ROW_NUMBER() OVER (PARTITION BY d.descriptionc, b.id ORDER BY c.date DESC ) AS rn FROM database.table1 a INNER JOIN database.table2 b ON a.id = b.table1_id INNER JOIN database.table3 c ON b.element = c.table2_element AND b.expdate >= Now() INNER JOIN database.table4 d ON c.value = d.table3_value WHERE a.company IN ( '000', '001', '002', '003', '004' ) ) x WHERE rn = 1;
Quelques lignes de données et le résultat attendu correspondant nous aideraient probablement à fournir une réponse plus précise.
Vous n'avez donc besoin que de la dernière ligne de quels groupes? Comment voyez-vous quelle ligne est plus récente qu'une autre? Peut-être que montrer tous les champs de toutes les tables pourrait aider
Copie possible de Sélectionnez la première ligne de chaque groupe GROUP BY?