MySQL & Left Join, wieso nicht alle Datensätze?
tannenbaum
- datenbank
Hi!
hier zuerst mal der relevante teil der DB:
----------
CREATE TABLE users
(uid
bigint(20) unsigned NOT NULL default '0', vid
int(10) unsigned NOT NULL default '0',oid
tinyint(3) unsigned NOT NULL default '0',ip
varchar(15) NOT NULL default '',PRIMARY KEY (uid
,vid
)) TYPE=MyISAM COMMENT='Users and Vote Table';
CREATE TABLE vote
(vid
int(10) unsigned NOT NULL auto_increment,name
varchar(200) NOT NULL default '',PRIMARY KEY (vid
),UNIQUE KEY name
(name
)) TYPE=MyISAM COMMENT='Main Vote Table' AUTO_INCREMENT=8 ;
CREATE TABLE vote\_option
(vid
int(10) unsigned NOT NULL default '0', oid
tinyint(3) unsigned NOT NULL default '0',name
varchar(200) NOT NULL default '',PRIMARY KEY (vid
,oid
)) TYPE=MyISAM COMMENT='Vote options';
INSERT INTO users
VALUES (101, 7, 2, '101');
INSERT INTO users
VALUES (102, 7, 3, '102');
INSERT INTO users
VALUES (103, 7, 3, '103');
INSERT INTO users
VALUES (104, 7, 4, '104');
INSERT INTO vote\_option
VALUES (7, 1, 'opt1');
INSERT INTO vote\_option
VALUES (7, 2, 'opt2');
INSERT INTO vote\_option
VALUES (7, 3, 'opt3');
INSERT INTO vote\_option
VALUES (7, 4, 'opt4');
INSERT INTO vote\_option
VALUES (7, 5, 'opt5');
----------
dann das SELECT-Query:
----------
SELECT options.oid, options.name AS name
, COUNT(*) AS votes
FROM BVP_vote_option options
LEFT JOIN BVP_users users
ON options.oid = users.oid WHERE users.vid = 7 GROUP BY users.oid ORDER BY votes
DESC
----------
und das Ergebnis:
----------
3 opt3 2
4 opt4 1
2 opt2 1
----------
das Problem:
müssten es nicht 5 Datensätze sein? der LEFT-JOIN ist ja dazu da dass alles angezeigt wird, ich hätte mir als Ergebniss sowas vorgestellt:
----------
3 opt3 2
4 opt4 1
2 opt2 1
1 opt1 0
5 opt5 0
----------
weiß jemmand was da schief gelaufen ist bzw. wie ich zum gewünschten Ergebnis komme?
thx
sry, hab vorhin beim db-teil eine zeile vergessen:
INSERT INTO BVP\_vote
VALUES (7, 'moo');
Hi,
ich glaube du hast Recht, aber die Datenbank leider auch. Da hast insoweit Recht, als dass rein von dem LEFT JOIN sämtliche Vote-Options rauskommen. Tun sie auch, sie sind nach dem Join tatsächlich noch übrig (behaupte ich), allerdings wendest du dann _nach_ dem JOIN ein WHERE-Kriterium an, und das haut sie raus.
Es könnte u.U. klappen, wenn du als User-ID auch NULL erlauben würdest.
MfG
Rouven
yo,
weiß jemmand was da schief gelaufen ist bzw. wie ich zum gewünschten Ergebnis komme?
drei dinge laufen bei dir schief.
zum einen die tabellennamen. wenn ich deine tabellen und daten eingebe, bekomme ich eine fehlermeldung, dass es die tabelle BVP_vote_option nicht gibt. und das macht auch sinn, heißen deine tabellen doch users, vote, und vote_option.
zweitens, das dbms führt erst den LEFT JOIN aus und dann die bedingung in der WHERE klausel. dies kann zu unerwarteten ergebnissen kommen, da damit quasi der OUTER JOIN ausgehebelt wird. dies kannst du umgehen, indem du die WHERE bedingung mit in die JOIN bedingung nimmst.
LEFT JOIN users
ON (options.oid = users.oid AND users.vid = 7)
drittens musst du mit deiner gruppierung, bzw, den spalten aufpassen, die du asugeben willst. mysql hat dort einen nicht optimalen weg eingeschlagen. grundsäzlich gilt, jede spalten die du ausgeben willst, muss auch mit in die GROUP BY klausel rein, ausgenommen sind aggregat-funktionen wie COUNT(). und daran würde ich mich auch halten, auch wenn mysql keine fehlermeldung ausgibt.
Ilja