phpbar.de logo

Mailinglisten-Archive

Sonderbares Verhalten bei einem SELECT

Sonderbares Verhalten bei einem SELECT

Cybot lists at sebastianmendel.de
Die Aug 5 14:37:21 CEST 2003


Ralf Eggert wrote:

> Hi Liste,
> 
> ich habe folgende 2 Tabellen (etwas vereinfacht):
> 
> CREATE TABLE syst_sites (
>   site_id tinyint(3) unsigned NOT NULL default '0',
>   site_name varchar(32) NOT NULL default '',
>   site_url varchar(64) default NULL,
>   site_email varchar(64) default NULL,
>   PRIMARY KEY  (site_id)
> ) TYPE=MyISAM;
> 
> CREATE TABLE cat_links (
>   link_id smallint(5) unsigned NOT NULL default '0',
>   link_site tinyint(3) unsigned NOT NULL default '0',
>   link_status enum('neu','genehmigt','geparkt','gesperrt') NOT NULL,
>   link_name varchar(64) NOT NULL default '',
>   link_url varchar(255) NOT NULL default '',
>   link_text varchar(255) NOT NULL default '',
>   PRIMARY KEY  (link_id),
>   UNIQUE KEY un_link_url (link_site,link_url),
>   KEY fk_link_site (link_site),
>   KEY in_link_sitestatus (link_site,link_status)
> ) TYPE=MyISAM;
> 
> Ich moechte mit einem Select eine Uebersicht aller "Sites" mit der
> Anzahl der Links gesamt und der Links mit Status "neu" erhalten. Mein
> Select sieht so aus:    
> 
>     SELECT syst_sites.*, 
>            COUNT(a_links.link_id) AS site_linkcnt, 
>            COUNT(b_links.link_id) AS site_linkcntnew
>       FROM syst_sites 
>  LEFT JOIN cat_links AS b_links 
>         ON site_id = b_links.link_site 
>        AND FIND_IN_SET('neu', b_links.link_status) 
>  LEFT JOIN cat_links AS a_links 
>         ON site_id = a_links.link_site 
>   GROUP BY site_id 
>   ORDER BY site_id 
> 
> Das erste sonderbare Verhalten ist, dass das SELECT-Statement ueber 3
> Sekunden braucht, wenn ich die Reihenfolge der LEFT JOINs vertausche,
> also zuerst auf "a_links" und dann auf "b_links" abfrage. Mache ich es
> so wie oben angegeben, benoetigt das SELECT-Statement nur 0,03x
> Sekunden.

ja weil bei 'erst a dann b' nach dem ersten join wesentlich mehr
datensätze zutreffen als bei 'erst b dann a'

> 
> Das andere Problem ist, dass im Ergebnis bei "site_linkcntnew" der
> gleiche Wert wie bei "site_linkcnt" steht, wenn es bei der "Site"
> zumindest einen Link gibt, der den Status "neu" hat. Bei allen anderen
> wird korrekterweise eine 0 ausgegeben. 

einfach mal ein SELECT * ohne das GROUP BY und das COUNT() und schau dir
an was er denn ausgibt (mit LIMIT 50 oder so)

> Kann mir jemand einen Tipp geben, wo das Problem liegen koennte oder wo
> im SELECT-Statement mein Denkfehler liegen koennte?
> 
> Danke und Gruss,
> 
>         Ralf
> 

du könntest mit ein wenig CASE das auch über _ein_ LEFT JOIN lösen:

*ungetested*

     SELECT syst_sites.*,
            COUNT(cat_links.link_id) AS site_linkcnt,
            SUM(CASE WHEN FIND_IN_SET('neu', cat_links.link_status)
                   THEN 1 ELSE 0 END) AS site_linkcntnew
       FROM syst_sites
  LEFT JOIN cat_links
         ON syst_sites.site_id = cat_links.link_site
   GROUP BY site_id
   ORDER BY site_id

oder so ähnlich...

-- 
Sebastian Mendel

www.sebastianmendel.de
www.tekkno4u.de
www.nofetish.com

-- 
Infos zur Mailingliste, zur Teilnahme und zum An- und Abmelden unter
-->>  http://www.4t2.com/mysql 


php::bar PHP Wiki   -   Listenarchive