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))) 
 
  
 
      |