SQL: Group par valeur minimale dans un champ tout en sélectionnant des lignes distinctes
voilà ce que j'essaie de faire. Disons que j'ai cette table t:
id | record_date | other_cols
18 | 2011-04-03 | x
18 | 2012-05-19 | y
18 | 2012-08-09 | z
19 | 2009-06-01 | a
19 | 2011-04-03 | b
19 | 2011-10-25 | c
19 | 2012-08-09 | d
pour chaque id, je veux sélectionner la ligne contenant le minimum record_date. Alors j'ai eu:
id | record_date | other_cols
18 | 2011-04-03 | x
19 | 2009-06-01 | a
les seules solutions que j'ai vu à ce problème supposent que toutes les entrées de record_date sont distinctes, mais ce n'est pas le cas dans mes données. L'utilisation d'un subquery et d'une jointure interne avec deux conditions me donnerait des lignes dupliquées pour certains ids, ce que je ne veux pas:
id | record_date | other_cols
18 | 2011-04-03 | x
19 | 2011-04-03 | b
19 | 2009-06-01 | a
7 réponses
Que Diriez-vous de quelque chose comme
SELECT mt.*,
FROM MyTable mt INNER JOIN
(
SELECT ID, MIN(Record_Date) MinDate
FROM MyTable
GROUP BY ID
) t ON mt.ID = t.ID AND mt.Record_Date = t.MinDate
obtient la date minimale par ID, puis obtient les valeurs basées sur ces valeurs. La seule fois où vous aurez des doublons, c'est s'il y a des doublons minimum record_dates pour le même ID.
pour obtenir le produit le moins cher dans chaque catégorie, vous utilisez la fonction MIN () dans une sous-commande corrélée comme suit:
SELECT categoryid,
productid,
productName,
unitprice
FROM products a WHERE unitprice = (
SELECT MIN(unitprice)
FROM products b
WHERE b.categoryid = a.categoryid)
la requête externe balaye toutes les lignes dans la table de produits et renvoie les produits qui ont des prix unitaires concordent avec le prix le plus bas dans chaque catégorie renvoyée par la sous-requête corrélée.
Cette vieille question, mais cela peut être utile pour quelqu'un Dans mon cas, je ne peux pas utiliser une requête secondaire parce que j'ai une grande requête et j'ai besoin d'utiliser min() sur mon résultat, si j'utilise une requête secondaire, la db doit ré-exécuter ma grande requête. j'utilise Mysql
select t.*
from (select m.*, @g := 0
from MyTable m --here i have a big query
order by id, record_date) t
where (1 = case when @g = 0 or @g <> id then 1 else 0 end )
and (@g := id) IS NOT NULL
Fondamentalement, j'ai commandé le résultat et puis mettre une variable afin d'obtenir uniquement le premier enregistrement de chaque groupe.
la requête ci-dessous prend la première date pour chaque ordre de travail (dans un tableau montrant tous les changements d'état):
SELECT
WORKORDERNUM,
MIN(DATE)
FROM
WORKORDERS
WHERE
DATE >= to_date('2015-01-01','YYYY-MM-DD')
GROUP BY
WORKORDERNUM
je voudrais ajouter à quelques-unes des autres réponses ici, si vous n'avez pas besoin de la premier article mais dire le deuxième nombre par exemple, vous pouvez utiliser rownumber dans un sous-jeu et de base votre résultat mis hors de cela.
SELECT * FROM
(
SELECT
ROW_NUM() OVER (PARTITION BY Id ORDER BY record_date, other_cols) as rownum,
*
FROM products P
) INNER
WHERE rownum = 2
cela vous permet également de commander des colonnes multiples dans le sous-questionnaire qui peut aider si deux record_dates ont des valeurs identiques. Vous pouvez aussi séparer plusieurs colonnes si nécessaire en les délimitant par une virgule
Ce ne simplement:
select t2.id,t2.record_date,t2.other_cols
from (select ROW_NUMBER() over(partition by id order by record_date)as rownum,id,record_date,other_cols from MyTable)t2
where t2.rownum = 1