Voici ma table des voitures qui a 1000 lignes. Chaque marque ou fabricant a un modèle différent et le même modèle peut avoir un prix différent. Je dois sortir le prix minimum parmi tous les modèles de chaque fabricant et je ne vois aucun moyen de le faire. Le plus proche de ce que j'ai obtenu est,
SELECT make, model, min(price) FROM car GROUP BY model, make ORDER BY make;
qui génère 527 lignes
Mais je veux un prix minimum parmi tous les modèles de chaque marque. AIDE !!
5 Réponses :
Dans Postgres, je recommande distinct sur à cet effet:
select distinct on (make) c.* from cars c order by make, price asc;
Ce type de commande SQL est nouveau pour moi. Pouvez-vous s'il vous plaît me guider plus sur où apprendre ce type de commande.
@MayankPant. . . DISTINCT ON est décrit dans la documentation: postgresql.org/docs/current/sql-select.html#SQL-DISTINCT .
D'après votre question, il semble que vous souhaitiez un prix minimum pour chaque marque. La requête suivante peut aider à mon avis.
SELECT make,MIN(price) from car group by make order by make;
Merci mais je veux aussi le nom du modèle dans la sortie.
En supposant que vous ayez besoin du "modèle le moins cher pour chaque marque", vous pouvez facilement obtenir le prix le plus bas par marque en fonction des réponses données, mais cela ne vous donnera pas le nom du modèle!
Je suggère d'utiliser une fonction de fenêtre pour classer les données, le partitionnement par marque et le classement par prix croissant. Ensuite, sélectionnez simplement toutes les lignes classées 1.
Il se peut que deux modèles d'une même marque soient proposés à des prix équivalents. Dans ce cas, vous auriez deux lignes renvoyées pour ce Make. Si c'est une possibilité et aussi un problème, vous devrez engager un traitement supplémentaire pour décider comment briser l'égalité ou consolider la ligne en une seule (par exemple, en concaténant les noms de modèle).
pouvez-vous s'il vous plaît élaborer votre paragraphe 2 ou me fournir des références pour le contexte?
@MayankPant, voir la réponse de Forpas pour un exemple de code (et mon commentaire).
Utilisez la fonction de fenêtre rank () à l'intérieur d'un CTE pour filtrer les prix minimum:
rank() over (partition by make, model order by price) rn
Cela renverra des liens au prix minimum .
Si vous n'avez pas besoin de liens, remplacez rank () par row_number () .
J'ai supposé qu'un nom de modèle ne pouvait pas être utilisé par 2 fabricants. Si ce n'est pas le cas, passez à ceci:
with cte as (
select *,
rank() over (partition by model order by price) rn
from car
)
select id, make, model, price
from cte
where rn = 1
order by make;
Ce type de commande SQL est nouveau pour moi. Pouvez-vous s'il vous plaît me guider plus sur où apprendre ce type de commande. Toute référence.
Vous pouvez lire la documentation officielle des fonctions de fenêtre: postgresql.org/docs/9.1/ tutorial-window.html et pour les CTE: postgresql.org/docs /9.1/queries-with.html
Forpas, vous souhaitez partitionner par marque dans ce cas - les modèles de chaque marque seront alors classés en fonction du prix.
@Steve maintenant je vois ce que vous voulez dire, mais je suppose que les noms de modèle sont uniques (ce qui signifie qu'un nom de modèle ne peut pas être utilisé par un autre fabricant), non? Donc pas besoin d'un autre niveau de partition.
@Forpas, je suppose que nous avons besoin de lui pour clarifier, mais le partitionnement par modèle (en supposant qu'aucune marque n'a un modèle du même nom) ne filtrera que les "doublons" les plus chers pour chaque modèle - il ne trouvera pas le modèle le moins cher par marque (c'est ainsi que j'ai déduit son exigence). S'il avait besoin de ce dernier, alors vous partitionneriez sur la marque et le modèle pour éviter la possibilité de filtrer les modèles du même nom sur deux marques différentes (une possibilité à distance avec les voitures que je concède, mais le potentiel est là - par exemple, la Jaguar 420 , une très vieille voiture et la BMW 420, une voiture moderne).
@Steve si seulement 420 peuvent servir de modèle, vous avez raison. J'ajouterai cela dans la partition comme solution potentielle.
Je pense que vous recherchez une simple jointure à gauche.
select t1.make, t1.model, t2.min_price from car t1 left join (select make, min(price) min_price from car group by make) t2 on t1.make=t2.make
Les exemples de données sont mieux présentés sous forme de texte formaté . Consultez ici pour obtenir des conseils sur la façon de créer de jolis tableaux.
En plus de ce que @a_horse_with_no_name a dit, veuillez ne pas utiliser la balise
databasesauf si vous avez une question sur la conception de la base de données.Copie possible de Sélectionnez la première ligne de chaque groupe GROUP BY?