Having / Group by / Aggregieren - Kompliziertere SQL Abfragen in einer
Tabelle
Vertiefungen & Übungen
Gerade beim Aggregieren von Daten zeigen sich die stärken von relationalen
DBMS und häufen sich auch die Schwierigkeiten was SQL Abfragen angeht.
Deshalb hier ein paar Beispiele wie Daten agregiert werden können
Eine Testtabelle mit Daten
CREATE TABLE `preis` ( `id` int(10) unsigned NOT NULL auto_increment, `user_id` int(10) unsigned NOT NULL default '0', `value` decimal(12,2) NOT NULL default '0.00', `info` varchar(250) NOT NULL default '', PRIMARY KEY (`id`) ) TYPE=MyISAM
# # Daten für Tabelle `preis` #
INSERT INTO `preis` VALUES (1001, 12, '12.00', 'Auto'); INSERT INTO `preis` VALUES (1002, 12, '112.00', 'Auto'); INSERT INTO `preis` VALUES (1003, 12, '212.00', 'Auto'); INSERT INTO `preis` VALUES (1004, 12, '312.00', 'Haus'); INSERT INTO `preis` VALUES (1005, 12, '412.00', 'Haus'); INSERT INTO `preis` VALUES (1006, 12, '512.00', 'Auto'); INSERT INTO `preis` VALUES (1007, 12, '612.00', 'Kino'); INSERT INTO `preis` VALUES (1008, 12, '62.00', 'Haus'); INSERT INTO `preis` VALUES (1009, 12, '512.00', 'Auto'); INSERT INTO `preis` VALUES (1010, 12, '62.00', 'Haus');
Select mit Group by und having
Mit GROUP BY aggregiert man Zeilen aufaggregieren, d.h. man
fasst Zeilen zusammen.
Mit Hilfe von HAVING grenzt man die gruppierte Ergebnismenge
ein.
Einfachste Anwendung:
SELECT count(*),info FROM preis GROUP BY info
SELECT count(*),info FROM preis GROUP BY info HAVING count(*)>2
Alle Agregierfunktionen dürfen bei Group by verwendet werden:
SELECT info, sum( value ) , avg( value ) , count( * ) , min( value ) , max( value ) FROM preis WHERE user_id = 12 GROUP BY info HAVING min( value ) > 100
Aufgaben:
Wie kann man diesen Subselect (der erst ab version 4.1 gehen soll!)
umschreiben?
SELECT * FROM preis WHERE id IN ( SELECT id FROM preis WHERE value > 100 )
Tip: Selfjoin
Wie können Doubletten (erkennbar an gleichem Value user_id und Info)
raussuchen?
select count(*), user_id, value, info from preis group by user_id, value, info having count(*) >1
Kann man das Löchen der Datensätze (nicht nur das finden!) auch automatisieren?
- Hint: Group by macht hin und wieder bei Date/Time Feldern Pobleme Abhilfe schaft
hier SEC_TO_TIME(SUM(TIME_TO_SEC(Datums_Time_Feld)))
|