2008-09-16 6 views
3

Je dois retourner une liste d'identifiants d'enregistrement à partir d'une table qui peut/peut ne pas avoir plusieurs entrées avec cet ID d'enregistrement à la même date. Le même critère de date est la clé - si un enregistrement a trois entrées le 09/10/2008, alors j'ai besoin de tous les trois retournés. Si l'enregistrement n'a qu'une entrée le 09/12/2008, je n'en ai pas besoin.Obtenir la liste des enregistrements avec plusieurs entrées à la même date

+0

Pour cette classe de problème, il est une bonne idée de préciser le SGBDR. Oracle peut utiliser des solutions que SQL Server ne peut pas et inversement. –

Répondre

3
SELECT id, datefield, count(*) FROM tablename GROUP BY datefield 
    HAVING count(*) > 1 
+0

Ceci renvoie tous les enregistrements dont la date est partagée par d'autres enregistrements. Je pense qu'il veut seulement les enregistrements qui ont plusieurs entrées avec la même date. – dbrien

1

GROUP BY avec HAVING est votre ami:

select id, count(*) from records group by date having count(*) > 1 
1
select id from tbl where date in 
(select date from tbl group by date having count(*)>1) 
1

Pour correspondre uniquement sur la partie date d'une valeur datetime:

select * from Table 
where id in (
    select alias1.id from Table alias1, Table alias2 
    where alias1.id != alias2.id 
     and datediff(day, alias1.date, alias2.date) = 0 
) 

Je pense. Cela est basé sur ma supposition que vous en avez besoin le même jour mois et année, mais pas le même moment de la journée, donc je n'ai pas utilisé une clause Grouper. D'après les autres messages, il semble que j'aurais pu utiliser plus intelligemment une clause Having. Pouvez-vous utiliser un avoir ou un groupe sur une expression de datediff?

1

Si je comprends bien votre question que vous pourriez faire quelque chose de similaire à:

select 
    recordID 
from 
    tablewithrecords as a 
    left join (
     select 
      count(recordID) as recordcount 
     from 
      tblwithrecords 
     where 
      recorddate='9/10/08' 
    ) as b on a.recordID=b.recordID 
where 
    b.recordcount>1 
1
SELECT * FROM the_table WHERE ROW(record_id,date) IN 
    (SELECT record_id, date FROM the_table 
    GROUP BY record_id, date WHERE COUNT(*) > 1) 
1

Puisque vous avez mentionné avoir besoin des trois enregistrements, je suppose que vous voulez également les données. Si vous avez juste besoin des identifiants, vous pouvez simplement utiliser le groupe par requête. Pour renvoyer les données, juste joindre à cela comme un sous-requête

select * from table 
inner join (
    select id, date 
    from table 
    group by id, date 
    having count(*) > 1) grouped 
     on table.id = grouped.id and table.date = grouped.date 
1

Je ne suis pas sûr d'avoir compris votre question, mais peut-être vous voulez quelque chose comme ceci:

SELECT id, COUNT(*) AS same_date FROM foo GROUP BY id, date HAVING same_date = 3; 

Ceci est juste écrit de mon esprit et non testé de quelque façon. Lisez la section GROUP BY et HAVING here. Si ce n'est pas ce que vous vouliez dire, veuillez ignorer cette réponse.

1

Notez qu'un traitement supplémentaire est nécessaire si vous utilisez un champ SQL DateTime. Si vous avez des données de temps supplémentaires, vous ne pouvez pas utiliser cette colonne telle quelle. Vous devez normaliser le DateTime à une seule valeur pour tous les enregistrements contenus dans le jour.

Dans SQL Server est ici un petit truc pour le faire:

SELECT CAST(FLOOR(CAST(CURRENT_TIMESTAMP AS float)) AS DATETIME) 

vous lancez le DateTime dans un flotteur, ce qui représente la date que la partie entière et le temps que la fraction d'un jour qui est passé. Découpez cette partie décimale, puis renvoyez-la à un DateTime, et vous avez minuit au début de cette journée.

1
 
SELECT id, count(*) 
INTO #tmp 
FROM tablename 
WHERE date = @date 
GROUP BY id 
HAVING count(*) > 1 

SELECT * 
FROM tablename t 
WHERE EXISTS (SELECT 1 FROM #tmp WHERE id = t.id) 

DROP TABLE tablename 
1

Sans connaître la structure exacte de vos tables ou le type de base de données que vous utilisez, il est difficile de répondre.Toutefois, si vous utilisez MS SQL et si vous avez un véritable champ date/heure qui a différentes reprises que les documents ont été saisis à la même date alors quelque chose comme cela devrait fonctionner:

select record_id, 
     convert(varchar, date_created, 101) as log date, 
     count(distinct date_created) as num_of_entries 
from record_log_table 
group by convert(varchar, date_created, 101), record_id 
having count(distinct date_created) > 1 

Hope this helps.

2

La publication supérieure (Leigh Caldwell) ne retournera pas les enregistrements en double et doit être modifiée à la baisse. Il identifiera les clés en double. De plus, cela ne fonctionnera pas si votre base de données ne permet pas au groupe de ne pas inclure tous les champs sélectionnés (beaucoup ne le font pas). Si votre champ de date inclut un horodatage, vous devrez le tronquer en utilisant l'une des méthodes documentées ci-dessus (je préfère: dateadd (jj, 0, datediff (jj, 0, @ DateHeure))).

Je pense que Scott Nichols a donné la bonne réponse et est ici un script pour le prouver:

declare @duplicates table (
id int, 
datestamp datetime, 
ipsum varchar(200)) 

insert into @duplicates (id,datestamp,ipsum) values (1,'9/12/2008','ipsum primis in faucibus') 
insert into @duplicates (id,datestamp,ipsum) values (1,'9/12/2008','Vivamus consectetuer. ') 
insert into @duplicates (id,datestamp,ipsum) values (2,'9/12/2008','condimentum posuere, quam.') 
insert into @duplicates (id,datestamp,ipsum) values (2,'9/13/2008','Donec eu sapien vel dui') 
insert into @duplicates (id,datestamp,ipsum) values (3,'9/12/2008','In velit nulla, faucibus sed') 

select a.* from @duplicates a 
inner join (select id,datestamp, count(1) as number 
       from @duplicates 
      group by id,datestamp 
      having count(1) > 1) b 
     on (a.id = b.id and a.datestamp = b.datestamp) 
2
SELECT RecordID 
FROM aTable 
WHERE SameDate IN 
    (SELECT SameDate 
    FROM aTable 
    GROUP BY SameDate 
    HAVING COUNT(SameDate) > 1) 
1

TrickyNixon écrit;

La publication supérieure (Leigh Caldwell) ne retournera pas d'enregistrements en double et doit être modifiée à la baisse.

Pourtant, la question ne pose pas de questions sur les enregistrements en double. Il pose des questions sur les ID d'enregistrement en double à la même date ...

GROUP-BY, AYANT l'air bien pour moi. Je l'ai déjà utilisé en production.

.

Quelque chose à surveiller:

SELECT ... FROM ... GROUP BY ... HAVING COUNT (*)> 1

Will, sur la plupart des systèmes de bases de données, exécutez en O (NlogN) temps. C'est une bonne solution. (Sélectionner O (N), trier O (NlogN), grouper par O (N), ayant O (N) - Pire des cas, la meilleure date, la date est indexée et l'opération de tri est plus efficace.)

.

Sélectionnez ... de ..., .... où a.data = b.date

Accordé seulement les idiots font une jointure cartésienne. Mais vous regardez O (N^2) temps. Pour certaines bases de données, cela crée également une table "temporaire". C'est insignifiant quand votre table n'a que 10 lignes. Mais ça va faire mal quand cette table grandira!

lien Ob: http://en.wikipedia.org/wiki/Join_(SQL)

Questions connexes