FAQ |
Kalender |
![]() |
#1 | |||
|
||||
Har WN som tidsfördriv
|
Utvecklar grejer till en kund som har webbhotell hos cliche. Har använt version 4.x när jag utvecklat koden, men upptäckte att cliche har version 3. Misstänker att versionsskillnaden är boven i dramat, eller är jag ute och cyklar här? Som sagt använder jag själv 4.x och får inte något felmeddelande av följande query (ej heller på scorpionshops server), men på cliche blir det fel:
Kod:
You have an error in your SQL syntax near '(SELECT p.category_id cId, COUNT(p.product_id) as category_product_count ' at line 4 Whole query: SELECT c.*, t.category_product_count FROM shop_category c LEFT JOIN (SELECT p.category_id cId, COUNT(p.product_id) as category_product_count FROM shop_product p GROUP BY p.category_id ) t ON t.cId = c.category_id Kod:
CREATE TABLE `shop_product` ( `product_id` int(11) unsigned NOT NULL auto_increment, `category_id` int(11) NOT NULL default '0', `product_price` decimal(15,4) NOT NULL default '0.0000', `product_is_call_for_price` tinyint(1) NOT NULL default '0', `product_is_always_free_shipping` tinyint(1) NOT NULL default '0', `product_date_added` datetime NOT NULL default '0000-00-00 00:00:00', `product_date_modified` datetime default NULL, `product_date_available` datetime default NULL, `product_image` tinytext, `product_quantity` int(11) NOT NULL default '0', `product_custom_id` varchar(32) default NULL, PRIMARY KEY (`product_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; Kod:
CREATE TABLE `shop_product` ( `product_id` int(11) unsigned NOT NULL auto_increment, `category_id` int(11) NOT NULL default '0', `product_price` decimal(15,4) NOT NULL default '0.0000', `product_is_call_for_price` tinyint(1) NOT NULL default '0', `product_is_always_free_shipping` tinyint(1) NOT NULL default '0', `product_date_added` datetime NOT NULL default '0000-00-00 00:00:00', `product_date_modified` datetime default NULL, `product_date_available` datetime default NULL, `product_image` tinytext, `product_quantity` int(11) NOT NULL default '0', `product_custom_id` varchar(32) default NULL, PRIMARY KEY (`product_id`) ) TYPE=MyISAM; Så här ser shop_category ut: Kod:
CREATE TABLE `shop_category` ( `category_id` int(11) unsigned NOT NULL auto_increment, `category_parent_id` int(11) NOT NULL default '0', `category_sort_order` int(3) default NULL, `category_image` varchar(128) default '', `category_date_added` datetime default NULL, `category_date_modified` datetime default NULL, PRIMARY KEY (`category_id`), KEY `NewIndex` (`category_parent_id`,`category_id`) ) TYPE=MyISAM; Mycket(!) tacksam för information om vad felet beror på! Lite kul kan man väl ha åt följande mail? Varför ens svara när man inte svarar på kundens frågor? (Ok jag vet att man får vad man betalar för, och jag ska försöka få kunden att byta webbhotell...) Citat:
|
|||
![]() |
![]() |
![]() |
#2 | ||
|
|||
Mycket flitig postare
|
Citat:
Subquerys kom ganska sent i mysql (v4.1 som det verkar). http://dev.mysql.com/doc/mysql/en/rewritin...subqueries.html |
||
![]() |
![]() |
![]() |
#3 | |||
|
||||
Har WN som tidsfördriv
|
Som jag misstänkte då med andra ord... Vill inte ändra min kod för att bli bakåtkompatibel egentligen. Men är det kanske dumt att använda subqueries överhuvudtaget? (Eftersom det nu kom så sent i MySQL...)
|
|||
![]() |
![]() |
![]() |
#4 | ||
|
|||
Mycket flitig postare
|
Om man använder mysql är subquerys dumt (eftersom det bara stöds i de senaste versionerna och mysqlinstallationer har en tendens att inte vara helt up-to-date), men annars är det ju ett utmärkt sätt att låta databasen göra jobbet istf att göra det själv i kod.
Dock är väl din fråga knappast något som verkligen kräver en subquery... Det gör den bara onödigt komplicerad. Kod:
SELECT c.category_id, c.category_name, count(*) FROM shop_category c, shop_product p WHERE c.category_id = p.category_id GROUP BY c.category_id, c.category_name Min query blir dessutom sannolikt snabbare eftersom den slipper göra en subquery. |
||
![]() |
![]() |
![]() |
#5 | |||
|
||||
Flitig postare
|
Citat:
|
|||
![]() |
![]() |
![]() |
#6 | ||
|
|||
Klarade millennium-buggen
|
OT:
Kod:
#!/usr/local/bin/perl -w use DBI; require ("database_login.pl"); my $blah = subnet_connect(); my $dbh = $$blah; ###### my ($sql,$sth,$sql2,$sth2,$t1,$t2,$t3,$t4,$iters); $iters = 100000; $sql = 'SELECT SQL_NO_CACHE COUNT(*) FROM article'; $sth = $dbh->prepare($sql); $t1 = time(); for($i=0;$i<$iters;$i++) { $sth->execute(); } $t2 = time(); $sth->finish(); $sql2 = 'SELECT SQL_NO_CACHE COUNT(id) FROM article'; $sth = $dbh->prepare($sql2); $t3 = time(); for($i=0;$i<$iters;$i++) { $sth->execute(); } $t4 = time(); $sth->finish(); print "COUNT(*) " . ($t2-$t1) . " seconds\n"; print "COUNT(id) " . ($t4-$t3) . " seconds\n"; $dbh->disconnect(); Körningar (3): Kod:
COUNT(*) 10.6 seconds COUNT(id) 11 seconds Kod:
* 5 seconds fält 5.8 seconds 100,000 frågor på en tabell med 1,000,000 rader ger en diff på ungefär 3,6% (om jag kommer ihåg min lågstadiematte rätt). I fallet med SELECT är skillnaden större, nämligen 13,8% med 1000 iterationer över 100 rader (den här växer då rätt snabbt till en betydande skillnad). |
||
![]() |
![]() |
![]() |
#7 | |||
|
||||
Har WN som tidsfördriv
|
Citat:
![]() Jag kommer inte att lyssna på ditt tips om att specifikt ange fält, utan kör på *. Visserligen håller jag med dig om att det i teorin är bäst att ange sina fält. Dock inte i praktiken ![]() EDIT: Det finns ett litet problem när jag byter till din query: De kategorier som är tomma (dvs det saknas produkter i dem) kommer inte med nu, vilket jag vill att de ska göra, och få en product_count på 0 eller NULL... Ska fundera på detta efter "frukost"... |
|||
![]() |
![]() |
![]() |
#8 | ||
|
|||
Klarade millennium-buggen
|
Det brukar man lösa med LEFT JOINS vs INNER JOINS.. Du använder nu en innerjoin, det innebär att raden bara visas om det finns ett fält i båda tabellerna du joinar som stämmer. En left tar alltid med om det finns något i den vänstra.
Hmm, jag inser just att mina benchmarks visar resulta tvärtom mot all vedertagen kunskap. Kan någon vara snäll att peka ut vad jag har gjort för fel, eller uppvisa resultat som påvisar annorlunda? ![]() |
||
![]() |
![]() |
![]() |
#9 | |||
|
||||
Har WN som tidsfördriv
|
Citat:
![]() Kod:
SELECT c.*, count(p.product_id) category_product_count FROM shop_category c LEFT JOIN shop_product p ON c.category_id = p.category_id GROUP BY c.category_id |
|||
![]() |
![]() |
Svara |
|
|