Avatar billede joe_dalton Nybegynder
14. oktober 2005 - 13:51 Der er 8 kommentarer og
1 løsning

Delete distinct?

Hej Experter.

Jeg har et lille problem som jeg håber der er nogen som kan hjælpe mig med.

Jeg har en tabel med en masse identiske poster. De har dog alle en unik primærnøgle, men ellers er mange af dem de samme. Jeg skal høre om man kan lave et SQL statement som kun sletter en af gangen af disse dubletter indtil der ikke er flere tilbage ?

God weekend og på forhånd tak! :D
Avatar billede tofte Juniormester
14. oktober 2005 - 14:04 #1
er det vigtigt at den sletter dem en af gangen, eller er det ok, at den bare ryder op i dubletter?
Avatar billede ldanielsen Nybegynder
14. oktober 2005 - 14:34 #2
Bruger du primærnøglen? Hvilken af et sæt identiske poster skal have lov at overleve?

Hvis det er ligemeget, så kan du gøre dette:

INSERT INTO Tabellen (col1, col2, col3) SELECT DISTINCT col1, col2, col3 FROM Tabellen

col1, col2, col3 erstattes med alle kolonner undtagen nøglen

Nu har du tilføjet nye poster, der er en samling af alle unikke poster der var. Så mangler du bare at slette alle gamle poster, så du har brug for at vide hvilke der er nye og gamle. Er ID'et identity? For så kan du starte med at registrere det største ID du har, og år denne INSERT har kørt slette alle der har ID <= den tidligere max værdi.
Avatar billede arne_v Ekspert
14. oktober 2005 - 21:56 #3
hvis vi siger at:
  tabellen hedder t
  den unikke primærnøgle hedder pk
  der er 2 felter som afgør om rækken er dublet eller ej der hedder v1 og v2

DELETE FROM t WHERE pk NOT IN (SELECT maxpk FROM (SELECT v1,v2,MAX(pk) maxpk FROM t GROUP BY v1,v2) tagg)
Avatar billede arne_v Ekspert
14. oktober 2005 - 21:56 #4
som altid når man sletter: test på test data først !!!!
Avatar billede arne_v Ekspert
14. oktober 2005 - 21:58 #5
CREATE TABLE t (pk INTEGER PRIMARY KEY, v1 INTEGER, v2 INTEGER, v3 VARCHAR(50))
GO

INSERT INTO t VALUES(1, 11, 12, 'Bla bla')
GO
INSERT INTO t VALUES(2, 11, 12, 'Der var engang')
GO
INSERT INTO t VALUES(3, 21, 22, '...')
GO

SELECT * FROM t
GO

SELECT v1,v2,MAX(pk) maxpk FROM t GROUP BY v1,v2
GO

SELECT pk FROM t WHERE pk NOT IN (SELECT maxpk FROM (SELECT v1,v2,MAX(pk) maxpk FROM t GROUP BY v1,v2) tagg)
GO

DELETE FROM t WHERE pk NOT IN (SELECT maxpk FROM (SELECT v1,v2,MAX(pk) maxpk FROM t GROUP BY v1,v2) tagg)
GO

SELECT * FROM t
GO

DROP TABLE t
GO
Avatar billede arne_v Ekspert
14. oktober 2005 - 21:59 #6
1> CREATE TABLE t (pk INTEGER PRIMARY KEY, v1 INTEGER, v2 INTEGER, v3 VARCHAR(50))
2> GO
1>
2> INSERT INTO t VALUES(1, 11, 12, 'Bla bla')
3> GO
(1 row affected)
1> INSERT INTO t VALUES(2, 11, 12, 'Der var engang')
2> GO
(1 row affected)
1> INSERT INTO t VALUES(3, 21, 22, '...')
2> GO
(1 row affected)
1>
2> SELECT * FROM t
3> GO
pk          v1          v2
        v3
----------- ----------- -----------
        --------------------------------------------------
          1          11          12
        Bla bla
          2          11          12
        Der var engang
          3          21          22
        ...

(3 rows affected)
1>
2> SELECT v1,v2,MAX(pk) maxpk FROM t GROUP BY v1,v2
3> GO
v1          v2          maxpk
----------- ----------- -----------
          11          12          2
          21          22          3

(2 rows affected)
1>
2> SELECT pk FROM t WHERE pk NOT IN (SELECT maxpk FROM (SELECT v1,v2,MAX(pk) max
pk FROM t GROUP BY v1,v2) tagg)
3> GO
pk
-----------
          1

(1 row affected)
1>
2> DELETE FROM t WHERE pk NOT IN (SELECT maxpk FROM (SELECT v1,v2,MAX(pk) maxpk
FROM t GROUP BY v1,v2) tagg)
3> GO
(1 row affected)
1>
2> SELECT * FROM t
3> GO
pk          v1          v2
        v3
----------- ----------- -----------
        --------------------------------------------------
          2          11          12
        Der var engang
          3          21          22
        ...

(2 rows affected)
1>
2> DROP TABLE t
3> GO
Avatar billede ldanielsen Nybegynder
14. oktober 2005 - 22:43 #7
Tja joe_dalton, det ser i hvert fald ud til at dit problem bliver løst.

arne_v's løsning er den rigtige hvis du har brug for at denne oprydning skal køre regelmæssigt. Det ville jo nok være nummer et hvis du i din programmering kunne sørge for at dubletterne ikke opstår igen.

Min løsning er "quick and dirty", og derfor let at forstå og hurtig at kode, men den er kun tænkt som en "engangs" ting.

Hvis din id, vi kalder den pk som arne gør, er identity, så kan du lave det sådan (tabellen hedder t og kolonnerne v1, v2 og v3):

--------------------

DECLARE @MaxPk int

SELECT MaxPk = Max(pk) FROM t

INSERT INTO t (v1, v2, v3) SELECT DISTINCT v1, v2, v3 FROM t

DELETE FROM t WHERE pk <= MaxPk

--------------------

men tag nu en backup inden!!!
Avatar billede joe_dalton Nybegynder
19. oktober 2005 - 10:18 #8
Hej alle. Tak for hjælpen men jeg fandt hurtigt ud af det selv!
Avatar billede ldanielsen Nybegynder
19. oktober 2005 - 10:25 #9
Ikke fordi det gør så meget, men du bad om en løsning, og du fik to. Hvorfor er det så at ingen af dem belønnes med point?
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester