======[SQL] Doppelte Daten======
Ich habe hier mal eine Testtabelle `mytable`. Diese hat eine eindeutige id, dann 2 Schlüsselfelder (`field_1` und `field_2`) sowie ein Feld mit einem Wert (das Feld `value`).
^ mytable ^^^^
^ id ^ field_1 ^ field_2 ^ value ^
| 1 | A | X | 1 |
| 2 | B | X | 2 |
| 3 | A | X | 4 |
| 4 | C | Z | 8 |
| 5 | A | X | 16 |
| 6 | C | Z | 32 |
=====Herausfinden aller mehrfach vorhandenen Datensätze=====
Als erstes versuche ich mal herauszufinden welche Schlüsselpaarkombinationen (`field_1` und `field_2`) mehrfach vorkommen. Dazu kann man die Tabelle nach den Schlüsselfelder gruppieren und Zählen. Wenn es mehr als 1 Eintrag pro Gruppierung hat, dann diese Gruppierung ausgeben.
SELECT
field_1,
field_2
FROM
mytable
GROUP BY
field_1,
field_2
HAVING
COUNT(*) > 1 -- nur jene auswählen die mehr als ein Datensatz haben
Um nun alle Datensätze anzuzeigen deren Schlüsselgruppierungen mehrfach vorkommen, kann man das Resultat von vorher mit der Tabelle zurück verbinden
SELECT
source.*
FROM
mytable AS source,
(
SELECT field_1, field_2 -- alle Group-Felder
FROM mytable
GROUP BY field_1, field_2 -- alle Group-Felder
HAVING COUNT(*) > 1 -- nur jene auswählen die mehr als ein Datensatz haben
) AS filter
WHERE
filter.field_1 = source.field_1 -- alle Group-Felder verknüpfen
AND filter.field_2 = source.field_2
Wie man sieht, ist die id=2 ausgefiltert, da der Datensatz eindeutig ist. Die nicht Eindeutigen werden ausgegeben
^ Datensätze deren Schlüssel merhfach vorkommt ^^^^
^ id ^ field_1 ^ field_2 ^ value ^
| 1 | A | X | 1 |
| 3 | A | X | 4 |
| 4 | C | Z | 8 |
| 5 | A | X | 16 |
| 6 | C | Z | 32 |
===== Gruppieren, summieren etc =====
Einfach noch einige schöne Dinge die man auf diese Art herleiten kann. Gruppierungen, Prozentberechnung etc.
SELECT
filter.group_id,
source.*,
filter.group_sum,
(source.value/filter.group_sum) * 100 AS percent_of_group
FROM
mytable AS source,
(
SELECT field_1, field_2,
SUM(value) AS group_sum,
@rownum := @rownum+1 AS group_id
FROM
(SELECT @rownum := 0) AS vars,
mytable
GROUP BY
field_1,
field_2
) AS filter
WHERE
filter.field_1 = source.field_1
AND filter.field_2 = source.field_2
ORDER BY
group_id,
id;
^ Daten mit Berechnungen über die Gruppe hinweg ^^^^^^^
^ group_id ^ id ^ field_1 ^ field_2 ^ value ^ group_sum ^ percent_of_group ^
| 1 | 1 | A | X | 1 | 21 | 4.7619 |
| 1 | 3 | A | X | 4 | 21 | 19.0476 |
| 1 | 5 | A | X | 16 | 21 | 76.1905 |
| 2 | 2 | B | X | 2 | 2 | 100.0000 |
| 3 | 4 | C | Z | 8 | 40 | 20.0000 |
| 3 | 6 | C | Z | 32 | 40 | 80.0000 |