WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   MySQL-fråga (https://www.wn.se/forum/showthread.php?t=21950)

etanders 2007-06-24 17:46

Har ett problem med att formulera en SQL-fråga. Jag vill få ut en lista med alla dubletter i min tabell, d.v.s. en slags "motsats" till DISTINCT.

Säg att jag har en tabell kunder som ser ut så här:

Kod:

id  fornamn  efternamn  adress  telefon
1  Olle    Karlsson  ...    ...
2  Pelle    Nilsson    ...    ...
3  Kalle    Nilsson    ...    ...
4  Olle    Karlsson  ...    ...
5  Pelle    Karlsson  ...    ...
6  Kalle    Olsson    ...    ...
7  Kalle    Nilsson    ...    ...
8  Olle    Karlsson  ...    ...

Då skulle jag vilja få ut raderna 1, 3, 4, 7, 8, eftersom dessa personer (förnamn + efternamn) förekommer mer än en gång i tabellen. (Det spelar alltså ingen roll om adress och telefon är samma eller inte.)

Jag kan komma på en fråga som denna
Kod:

SELECT DISTINCT CONCAT(fornamn, " ", efternamn) AS namn, COUNT(*) AS antal FROM kunder GROUP BY namn HAVING antal > 1
för att plocka ut de namn som förekommer mer än en gång i tabellen. Problemet är bara att denna fråga ger mig ett resultat som
Kod:

Olle Karlsson
Kalle Nilsson

när vad jag är ute efter är hela tabellraderna, eller åtminstone id-numren på alla förekomster.

Någon som har något tips?

oller 2007-06-24 21:02

Kanske inte den snyggaste lösningen:

Kod:

SELECT * FROM kunder a, kunder b WHERE CONCAT(a.fornamn, " ", a.efternamn)=CONCAT(b.fornamn, " ",b.efternamn ) AND a.id!=b.id GROUP BY a.id
Mvh

etanders 2007-06-25 00:56

Oller, ditt förslag förstår jag inte... Det fungerar inte alls. Vad skulle följande betyda över huvud taget?

Kod:

SELECT * FROM kunder a, kunder b
Det går naturligtvis att göra en "ful" lösning genom att ta resultatet från min första fråga
Kod:

SELECT DISTINCT CONCAT(fornamn, " ", efternamn) AS namn, COUNT(*) AS antal FROM kunder GROUP BY namn HAVING antal > 1
och sedan med hjälp av en for-loop i php-koden köra en massa nya frågor, t.ex. som
Kod:

SELECT * FROM kunder WHERE CONCAT(fornamn, " ", efternamn) = $namn
Det skulle bara vara roligare/kännas bättre om det fanns något snyggare och/eller effektivare sätt. Funderade på något sånt här
Kod:

SELECT *
FROM kunder
WHERE CONCAT(fornamn, " ", efternamn) IN
  (SELECT
  DISTINCT CONCAT(fornamn, " ", efternamn) AS namn,
  COUNT(*) AS antal
  FROM kunder
  GROUP BY namn
  HAVING antal > 1)

men det funkar inte eftersom sub-frågan returerar två kolumner. Finns det något smart SQL-kommando för att komma runt detta?

WizKid 2007-06-25 01:03

Det fungerar inte bara med
Kod:

SELECT *
FROM kunder
WHERE CONCAT(fornamn, " ", efternamn) IN
  (SELECT
  DISTINCT CONCAT(fornamn, " ", efternamn) AS namn
  FROM kunder
  GROUP BY namn
  HAVING COUNT(*) > 1)


grazzy 2007-06-25 01:25

Slän på GROUP_CONCAT(id) AS ids så kommer du förhoppningsvis att få namnet + en lista med namnen.

Kod:

SELECT DISTINCT CONCAT(fornamn, \" \", efternamn) AS namn, GROUP_CONCAT(id) AS ids, COUNT(*) AS antal FROM kunder GROUP BY namn HAVING antal > 1
.. kanske?

etanders 2007-06-25 01:32

WizKid, det verkar inte som om det funkar. Om det gör det tar det i alla fall längre tid än jag orkade vänta...

Grazzy, tack för ditt förslag! Jag kände inte till GROUP_CONCAT tidigare, men det var en intressant variant som absolut kan komma till användning!

oller 2007-06-25 11:32

Citat:

Originally posted by etanders@Jun 25 2007, 00:56
Oller, ditt förslag förstår jag inte... Det fungerar inte alls. Vad skulle följande betyda över huvud taget?

Kod:

SELECT * FROM kunder a, kunder b

Kod:

SELECT * FROM kunder a, kunder b
innebär en cross join med samma tabell.

Frågan funkar för mig med följande data:
Kod:

mysql> select version();
+-----------+
| version() |
+-----------+
| 5.0.37  |
+-----------+
1 row in set (0.00 sec)

mysql> describe kunder;
+-----------+--------------+------+-----+---------+----------------+
| Field  | Type    | Null | Key | Default | Extra    |
+-----------+--------------+------+-----+---------+----------------+
| id    | int(11)  | NO  | PRI | NULL  | auto_increment |
| fornamn  | varchar(200) | NO  |  |    |        |
| efternamn | varchar(200) | NO  |  |    |        |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM kunder a, kunder b WHERE CONCAT(a.fornamn, " ", a.efternamn)=CONCAT(b.fornamn, " ",b.efternamn ) AND a.id!=b.id GROUP BY a.id
  ->;
+----+---------+-----------+----+---------+-----------+
| id | fornamn | efternamn | id | fornamn | efternamn |
+----+---------+-----------+----+---------+-----------+
| 1 | Olle  | Karlsson | 4 | Olle  | Karlsson |
| 3 | Kalle  | Nilsson  | 7 | Kalle  | Nilsson  |
| 4 | Olle  | Karlsson | 1 | Olle  | Karlsson |
| 7 | Kalle  | Nilsson  | 3 | Kalle  | Nilsson  |
| 8 | Olle  | Karlsson | 1 | Olle  | Karlsson |
+----+---------+-----------+----+---------+-----------+
5 rows in set (0.00 sec)


Magnus_A 2007-06-25 17:04

Se upp med den begränsning i längd som finns som standard i GROUP_CONCAT. Max längd sätts om standard till 1024 tecken om man inte ändrar i inställningarna. Räcker i och för sig till en hel del dubletter men om man vill använda GROUP_CONCAT till annat så bör man var medveten om denna begränsning.


Alla tider är GMT +2. Klockan är nu 08:24.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson