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
40
demandé sur user2765924 2013-09-10 21:17:56

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.

55
répondu Adriaan Stander 2013-09-10 17:34:37

je pourrais obtenir votre résultat attendu juste en faisant cela dans :

 SELECT id, min(record_date), other_cols 
  FROM mytable
  GROUP BY id

ça vous va?

9
répondu Math 2017-03-08 17:49:31

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.

3
répondu DIMI 2016-02-24 23:52:37

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.

0
répondu Luciano Marqueto 2016-05-05 21:03:39

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
0
répondu SRVFan 2018-04-30 23:26:32

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

0
répondu Reese De Wind 2018-06-06 14:26:24

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
-1
répondu jeff 2016-11-08 18:35:20