Utilisation d'une clause DISTINCT pour filtrer les données mais toujours extraire d'autres champs qui ne sont pas DISTINCT
Je suis en train d'écrire une requête dans Postgresql qui tire un ensemble de données classées et des filtres par un champ distinct. J'ai aussi besoin de tirer plusieurs autres champs de la même table de la ligne, mais ils doivent être en reste de la distinct de l'évaluation. exemple:
SELECT DISTINCT(user_id) user_id,
created_at
FROM creations
ORDER BY created_at
LIMIT 20
J'ai besoin de la user_id
être DISTINCT
mais ne se soucient pas si la created_at date est unique ou pas. Parce que le created_at date est incluse dans l'évaluation, je suis en double user_id
dans mon jeu de résultats.
Aussi, les données doivent être commandés par la date, l'utilisation d'un DISTINCT ON
n'est pas une option ici. - Il nécessaire que la DISTINCT ON
champ soyez le premier champ dans la ORDER BY
clause et qui ne livre pas les résultats que je cherche.
Comment puis-je utiliser correctement le DISTINCT
clause, mais limite sa portée aux seuls un champ encore en sélectionnant d'autres domaines?
source d'informationauteur mindtonic
Vous devez vous connecter pour publier un commentaire.
Comme vous l'avez découvert, standard SQL traite
DISTINCT
comme s'appliquant à l'ensemble de la liste de sélection, ne pas simplement une colonne ou un peu de colonnes. La raison pour cela est qu'il est ambigu de la valeur à mettre dans les colonnes de vous exclure de laDISTINCT
. Pour la même raison, le standard SQL ne permet pas d'avoir ambigu colonnes dans une requête avecGROUP BY
.Mais PostgreSQL dispose d'une extension non standard de SQL pour permettre ce que vous demandez:
DISTINCT ON (expr)
.Vous devez inclure l'expression distincte(s) que la partie gauche de votre clause ORDER BY.
Voir le manuel sur La Clause DISTINCT pour plus d'informations.
La
GROUP BY
devrait s'assurer différentes valeurs des colonnes groupées, cela pourrait vous donner ce que vous êtes après.(Note que je vais mettre dans mes 2 cents, même si je ne suis pas familier avec PostgreSQL, mais plutôt de MySQL et Oracle)
Dans MySql
Dans Oracle sqlplus
Ils vous donneront l'
user_id
suivie par la premièrecreated_at
associés à ceuser_id
. Si vous souhaitez une autrecreated_at
vous avez la possibilité de remplacer d'ABORD avec d'autres fonctions comme leAVG
MIN
MAX
ouLAST
dans Oracle, vous pouvez aussi essayer d'ajouterORDER BY
sur les autres colonnes (y compris ceux qui ne sont pas retournés, pour vous donner un autrecreated_at
.Votre question n'est pas bien défini - quand vous dites que vous avez besoin également d'autres données de la même rangée que vous n'êtes pas définir de qui ligne.
Vous faire dire que vous devez trier les résultats par
created_at
donc je vais assumer que vous souhaitez que les valeurs de la ligne avec mincreated_at
(la plus ancienne).Cela devient maintenant l'un des plus commun de sorte que SQL questions - récupération des lignes contenant une certaine valeur totale (MIN, MAX).
Par exemple
Cette approche ne vous laissera pas (facilement) prendre d'autres valeurs de la même ligne.
Une approche qui vous permettra de choisir d'autres valeurs est
Si vous voulez le plus récent created_at pour chaque utilisateur, puis-je vous suggérer d'agrégation comme ceci:
Ce sera le retour de la plus récente created_at pour chaque user_id
Si vous voulez seulement le top 20, puis ajouter
EDIT: C'est fondamentalement la même chose de la Déraison dit ci-dessus... de définir à partir de quelle ligne vous voulez que les données par agrégation.
En utilisant une sous-requête a été suggéré par quelqu'un sur irc #postgresql canal. Il a travaillé: