web-dev-qa-db-fra.com

Recherche de lignes avec le même identifiant mais une date différente

Considérez ci-dessous le tableau tbl:

id    date
1     2016
1     2017
2     2017
2     2017
3     2016
3     2017
4     2018
5     2018

Comment puis-je obtenir uniquement des lignes avec le même identifiant mais une date différente.

Pour le moment, je ne peux obtenir que des identifiants avec plus d'un compte comme ceci:

select id, date
from tbl
group by id
having count(id)>1

Comment puis-je obtenir uniquement les identifiants 1 et 3 avec la date?

1
MYGz

Utilisez une fonction AGGREGATE comme MIN ou MAX.

Si vous ne voulez qu'un seul enregistrement par ID, vous devez choisir la date souhaitée. Le premier (MIN) ou le dernier (MAX).

https://docs.Microsoft.com/en-us/sql/t-sql/functions/aggregate-functions-transact-sql?view=sql-server-2017

^^ Les informations ci-dessus ne correspondent pas à ce qui a été demandé.

Modifié par clarification dans les commentaires: utilisez simplement HAVING pour identifier les valeurs d'ID qui ont plus d'une date, puis appliquez-les à un nouveau SELECT.

SELECT id, Date
FROM tbl
WHERE id IN
    (
        select id 
        from tbl
        group by id
        having count(distinct date)>1
    )
6
MguerraTorres

Quelques autres façons d'obtenir le même résultat:

Premièrement, en utilisant min(date) < max(date) comme condition HAVING - au lieu de count(distinct date) > 1. Peut-être un peu plus efficace:

select id, date
from tbl
where id in 
      ( select id
        from tbl
        group by id
        having min(date) < max(date)
      ) ;

ou avec un JOIN:

select t.id, t.date
from tbl as t
     join 
      ( select id
        from tbl
        group by id
        having min(date) < max(date)
      ) as g
      on g.id = t.id ;

et une conversion de la sous-requête IN en une sous-requête EXISTS corrélée. Bonus, nous pouvons supprimer le GROUP BY:

select id, date
from tbl as t
where exists
      ( select 1
        from tbl as t2
        where t.id = t2.id
          and t.date <> t2.date
      ) ;

Un autre qui utilise des fonctions de fenêtre:

select id, date
from
  ( select id, date,
           diff_dates = case when min(date) over (partition by id)
                                < max(date) over (partition by id)
                             then 1
                        end 
    from tbl
  ) as d
where diff_dates = 1 ;

et enfin, un pour le concours d'obscurcissement:

select id, date from tbl
except
select id, min(date) from tbl group by id
intersect
select id, max(date) from tbl group by id ;

Testez dans dbfiffle.

5
ypercubeᵀᴹ

Vous devez compter, comme vous l'avez fait, et compter séparément par date

SELECT T.id,T.date
FROM Table1 AS T
CROSS APPLY
  (SELECT C.id 
          ,Count(id) as count_id
          ,Count(Distinct date) as count_Distinct_Records
      FROM Table1 AS C
      WHERE C.id = T.id
      GROUP BY id) AS CA
WHERE
  CA.count_id > 1
  AND count_Distinct_Records > 1

sortie ici:

id  date
1   2016
1   2017
3   2016
3   2017

dbfiddle

2
Sabin Bio