JOIN Problem. Komplex oder nur zu dumm?

JOIN Problem. Komplex oder nur zu dumm?

am 04.06.2006 20:12:15 von Thomas Berg

Ich habe eine Tabelle mit Clubs, eine Tabelle mit Events der Events und
eine mit Datums der Events (ein Event kann an mehreren Tagen stattfinden)

Ich benötige folgende Abfrage:
Anzeige ALLER Clubs und welche Aktionen an diesem Tag stattfinden.
<- Die Anzeige benötige ich bei der Administration. Falls noch kein Event
statt findet, möchte ich diesen mit einem Klick hinzufügen können.

hier die Tabellenstruktur:
unten die Abfrage, wie ich sie bis jetzt hab
--
-- Tabellenstruktur für Tabelle `cal_dates`
--
DROP TABLE IF EXISTS `cal_dates`;
CREATE TABLE `cal_dates` (
`EventID` mediumint(8) unsigned NOT NULL default '0',
`Date` date default NULL,
KEY `IDX_CalID` (`EventID`),
KEY `IDX_Date` (`Date`)
) TYPE=MyISAM PACK_KEYS=1;

--
-- Daten für Tabelle `cal_dates`
--

INSERT INTO `cal_dates` (`EventID`, `Date`) VALUES (1, '2006-06-12'),
(1, '2006-07-05'),
(2, '2006-12-29'),
(2, '2006-12-22');


-- --------------------------------------------------------

--
-- Tabellenstruktur für Tabelle `cal_events`
--
DROP TABLE IF EXISTS `cal_events`;
CREATE TABLE `cal_events` (
`ID` mediumint(8) unsigned NOT NULL auto_increment,
`ParentID` mediumint(8) unsigned NOT NULL default '0',
`Title` varchar(100) default NULL,
PRIMARY KEY (`ID`)
) TYPE=MyISAM PACK_KEYS=1 AUTO_INCREMENT=4 ;

--
-- Daten für Tabelle `cal_events`
--

INSERT INTO `cal_events` (`ID`, `ParentID`, `Title`) VALUES (1, 1,'Titel
1'),
(2, 1,'Titel 2'),
(3, 2,'Titel 3');

-- --------------------------------------------------------

--
-- Tabellenstruktur für Tabelle `clubs_main`
--
DROP TABLE IF EXISTS `clubs_main`;
CREATE TABLE `clubs_main` (
`ID` smallint(5) unsigned NOT NULL auto_increment,
`Title` varchar(60) default NULL,
PRIMARY KEY (`ID`)
);
INSERT INTO `clubs_main` (`ID`, `Title`) VALUES (1, 'Club 1'), (2, 'Club
2'), (3, 'Club 3');


###################################################
hier meine bis jetzt erstellte Abfrage. Sie zeigt mir alle Clubs mit allen
Terminen an.
Nun muß nur noch das auf ein bestimmtes Datum beschränkt werden.

SELECT * FROM `clubs_main`
LEFT OUTER JOIN `cal_events` ON (`cal_events`.`ParentID` =
`clubs_main`.`ID`)
LEFT JOIN `cal_dates` ON (`cal_dates`.`EventID` = `cal_events`.`ID`)

was nicht funktioniert
WHERE (`cal_dates`.`Date` = 2006-12-01 OR `cal_dates`.`Date` is NULL)
:-(
#####################################

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 01:10:59 von Norbert Melzer

Thomas Berg schrieb:
> hier die Tabellenstruktur:
> unten die Abfrage, wie ich sie bis jetzt hab

....

und wie weiter???
Da hört Deine Nachricht bei mir auf...

Norbert

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 05:12:28 von Stefan Rybacki

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Thomas Berg schrieb:
>...

>was nicht funktioniert
>WHERE (`cal_dates`.`Date` = 2006-12-01 OR `cal_dates`.`Date` is NULL)
> :-(
>#####################################

Setze das Datum in Hochkommas ansonsten testest du gegen 2006-12-01=1993.

Bis denn dann
Stefan

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (MingW32)

iD8DBQFEg6EcyeCLzp/JKjARAm6aAKCVFr0pssrIW42WsdzvFqYnVbK2ugCf V4xx
eBTguNy+7wyyohuysTFMzac=
=h3wE
-----END PGP SIGNATURE-----

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 08:37:00 von dnoeth

Stefan Rybacki wrote:

>> was nicht funktioniert
>> WHERE (`cal_dates`.`Date` = 2006-12-01 OR `cal_dates`.`Date` is NULL)
>> :-(
>> #####################################
>
> Setze das Datum in Hochkommas ansonsten testest du gegen 2006-12-01=1993.


Die Bedingung gehört nicht in den WHERE-Teil, sondern mit AND in den
Join, sonst wird aus dem Outer ein Inner Join.

Dieter

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 11:57:20 von Matthias Esken

On Mon, 05 Jun 2006 01:10:59 +0200, Norbert Melzer wrote:

> Thomas Berg schrieb:
>> hier die Tabellenstruktur:
>> unten die Abfrage, wie ich sie bis jetzt hab
>
> ...
>
> und wie weiter???
> Da hört Deine Nachricht bei mir auf...

Er hat da einen Signatur-Trenner stehen.

Gruß,
Matthias

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 13:15:52 von Alex Hepp

Dieter Noeth schrieb am 05.06.2006 08:37:
>
> Die Bedingung gehört nicht in den WHERE-Teil, sondern mit AND in den
> Join, sonst wird aus dem Outer ein Inner Join.
>
> Dieter

Nein, nein...

Was sagt uns das Manual:

"Sie sollten nie irgend welche Bedingungen im ON-Teil haben, die dazu benutzt
werden, um die Zeilen, die im Ergebnissatz auftauchen, zu beschränken. Wenn Sie
so etwas tun wollen, müssen Sie das in der WHERE-Klausel tun."

gruß Alex

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 14:01:05 von Axel Schwenke

Alex Hepp wrote:
> Dieter Noeth schrieb am 05.06.2006 08:37:
>>
>> Die Bedingung gehört nicht in den WHERE-Teil, sondern mit AND in den
>> Join, sonst wird aus dem Outer ein Inner Join.
>
> Nein, nein...
>
> Was sagt uns das Manual:
>
> "Sie sollten nie irgend welche Bedingungen im ON-Teil haben, die dazu benutzt
> werden, um die Zeilen, die im Ergebnissatz auftauchen, zu beschränken. Wenn Sie
> so etwas tun wollen, müssen Sie das in der WHERE-Klausel tun."

man "verstehendes Lesen"

Eine NOT NULL Bedingung - auch eine eine nicht-JOIN Spalte - auf
die rechte Tabelle degradiert einen LEFT JOIN zu einem INNER JOIN.
Das passiert nicht, wenn man das in die JOIN-Bedingung schreibt.

Vermutlich wollte der OP aber sowieso einen INNER JOIN. Erstaunlich
viele Anwender schreiben unnötige OUTER JOINs. Spitzenreiter war
ein ehemaliger Kollege mit folgendem Kleinod (sinngemäß):

SELECT ... FROM foo LEFT JOIN bar USING (id) WHERE bar.id NOT NULL

Die History (der Kram war CVS-versioniert) zeigte dann, daß da
ursprünglich mal ein INNER JOIN stand. Dann änderte sich die Logik
der Anwendung dahingehend, daß ein LEFT JOIN notwendig wurde. Dann
änderte sich die Logik wieder zurück und obiges passierte ;-)

Ach ja, gefunden habe ich das bei einem Performance-Review, weil
der OUTER JOIN ca. 100-mal langsamer war als ein INNER JOIN.


XL

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 16:26:11 von Thomas Berg

Hmm. Und wie soll nun die Abfrage aussehen?
Ich habe echt schon alle (falschen) Möglichkeiten getestet.
Hochkommata: Selbst wenn das Datum falsch wäre, sollen dann - wie bei einem
Datum, bei dem es keine Termine gibt - wenigstens alle Klubs ausgeworfen
werden.

Kurz nochmal: Ich benötige eine Abfrage, die immer alle Klubs auswirft UND
zusätzlich die - falls vorhanden - Termine

"Axel Schwenke" schrieb im Newsbeitrag
news:1e616e.20i.ln@idefix.xl.local...
> Alex Hepp wrote:
>> Dieter Noeth schrieb am 05.06.2006 08:37:
>>>
>>> Die Bedingung gehört nicht in den WHERE-Teil, sondern mit AND in den
>>> Join, sonst wird aus dem Outer ein Inner Join.
>>
>> Nein, nein...
>>
>> Was sagt uns das Manual:
>>
>> "Sie sollten nie irgend welche Bedingungen im ON-Teil haben, die dazu
>> benutzt
>> werden, um die Zeilen, die im Ergebnissatz auftauchen, zu beschränken.
>> Wenn Sie
>> so etwas tun wollen, müssen Sie das in der WHERE-Klausel tun."
>
> man "verstehendes Lesen"
>
> Eine NOT NULL Bedingung - auch eine eine nicht-JOIN Spalte - auf
> die rechte Tabelle degradiert einen LEFT JOIN zu einem INNER JOIN.
> Das passiert nicht, wenn man das in die JOIN-Bedingung schreibt.
>
> Vermutlich wollte der OP aber sowieso einen INNER JOIN. Erstaunlich
> viele Anwender schreiben unnötige OUTER JOINs. Spitzenreiter war
> ein ehemaliger Kollege mit folgendem Kleinod (sinngemäß):
>
> SELECT ... FROM foo LEFT JOIN bar USING (id) WHERE bar.id NOT NULL
>
> Die History (der Kram war CVS-versioniert) zeigte dann, daß da
> ursprünglich mal ein INNER JOIN stand. Dann änderte sich die Logik
> der Anwendung dahingehend, daß ein LEFT JOIN notwendig wurde. Dann
> änderte sich die Logik wieder zurück und obiges passierte ;-)
>
> Ach ja, gefunden habe ich das bei einem Performance-Review, weil
> der OUTER JOIN ca. 100-mal langsamer war als ein INNER JOIN.
>
>
> XL

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 18:52:01 von Axel Schwenke

"Thomas Berg" wrote:
> "Axel Schwenke" schrieb

>> Vermutlich wollte der OP aber sowieso einen INNER JOIN.

> Hochkommata: Selbst wenn das Datum falsch wäre, sollen dann - wie bei einem
> Datum, bei dem es keine Termine gibt - wenigstens alle Klubs ausgeworfen
> werden.

Stimmt, das hatte ich wohl überlesen. Damit brauchst du die Klubs-
Tabelle auf der linken Seite in einem LEFT JOIN. Aber der JOIN
zwischen Events und Dates kann ein INNER JOIN sein.

> Hmm. Und wie soll nun die Abfrage aussehen?

Z.B. so

SELECT ...
FROM ereignis
INNER JOIN datum
ON ereignis.id = datum.ereignis_id AND datum.wann = $X
RIGHT JOIN klub
ON klub.id = ereignis.klub_id


HTH, XL

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 20:48:57 von Thomas Berg

> SELECT ...
> FROM ereignis
> INNER JOIN datum
> ON ereignis.id = datum.ereignis_id AND datum.wann = $X
> RIGHT JOIN klub
> ON klub.id = ereignis.klub_id
>
Umgesetzt wird es dann so heißen:
SELECT *
FROM cal_events
INNER JOIN cal_dates
ON cal_events.ID = cal_dates.EventID AND cal_dates.Date =
'2006-06-12'
RIGHT JOIN clubs_main
ON clubs_main.ID = cal_events.ParentID
Ergebnis:
1 1 Titel 1 1 2006-06-12 1 Club 1
2 1 Titel 2 NULL NULL 1 Club 1
3 2 Titel 3 NULL NULL 1 Club 1
1 1 Titel 1 NULL NULL 2 Club 2
2 1 Titel 2 NULL NULL 2 Club 2
3 2 Titel 3 NULL NULL 2 Club 2
1 1 Titel 1 NULL NULL 3 Club 3
2 1 Titel 2 NULL NULL 3 Club 3
3 2 Titel 3 NULL NULL 3 Club 3


Bei den vielen "Datums" hier sind es zwar nur 9, aber in der Datenbank
werden viel mehr sein, wird es recht unübersichtlich.
Sicher könnte ich die NULL mit PHP filtern, aber ich würde es gerne schon
mit MySQL machen. So soll das Ergebnis aussehen:

1 1 Titel 1 1 2006-06-12 1 Club 1
1 1 Titel 1 NULL NULL 2 Club 2
3 2 Titel 3 NULL NULL 3 Club 3


Beim ersten Club gibt es ein Event, bei den anderen nicht, aber sie
erscheinen trotzdem.

Geht das?

Re: JOIN Problem. Komplex oder nur zu dumm?

am 05.06.2006 23:09:09 von Axel Schwenke

"Thomas Berg" wrote:
/me wrote:

>> SELECT ...
>> FROM ereignis
>> INNER JOIN datum
>> ON ereignis.id = datum.ereignis_id AND datum.wann = $X
>> RIGHT JOIN klub
>> ON klub.id = ereignis.klub_id
>>
> Umgesetzt wird es dann so heißen:
....

Ja, das wollte ich dir zur Übung überlassen :-)

> Ergebnis:
> 1 1 Titel 1 1 2006-06-12 1 Club 1
> 2 1 Titel 2 NULL NULL 1 Club 1
> 3 2 Titel 3 NULL NULL 1 Club 1
> 1 1 Titel 1 NULL NULL 2 Club 2
> 2 1 Titel 2 NULL NULL 2 Club 2
> 3 2 Titel 3 NULL NULL 2 Club 2
> 1 1 Titel 1 NULL NULL 3 Club 3
> 2 1 Titel 2 NULL NULL 3 Club 3
> 3 2 Titel 3 NULL NULL 3 Club 3
....

> So soll das Ergebnis aussehen:
>
> 1 1 Titel 1 1 2006-06-12 1 Club 1
> 1 1 Titel 1 NULL NULL 2 Club 2
> 3 2 Titel 3 NULL NULL 3 Club 3

Genau so sieht das hier auch aus. Welche MySQL-Version hast du?

+------+----------+---------+---------+------------+----+--- -----+
| ID | ParentID | Title | EventID | Date | ID | Title |
+------+----------+---------+---------+------------+----+--- -----+
| 1 | 1 | Titel 1 | 1 | 2006-06-12 | 1 | Club 1 |
| NULL | NULL | | NULL | | 2 | Club 2 |
| NULL | NULL | | NULL | | 3 | Club 3 |
+------+----------+---------+---------+------------+----+--- -----+

+-----------+
| VERSION() |
+-----------+
| 5.0.20 |
+-----------+

Falls du genau die geposteten Daten und genau die gepostete Query
verwendet hast, scheint ein Bug in deinem MySQL zu sein. Ein Workaround
wäre dann, SELECT DISTINCT ... zu schreiben.


PS: Ich stelle mit Wohlgefallen fest, daß du das zweite Mal richtig
zitiert hast. Obwohl ich vergessen hatte, dich auf dein Fullquote
aufmerksam zu machen.


XL

Re: JOIN Problem. Komplex oder nur zu dumm?

am 06.06.2006 00:18:23 von Thomas Berg

> +-----------+
> | VERSION() |
> +-----------+
> | 5.0.20 |
> +-----------+
es war eine 4.0 Version. Nun 5.0.22. Jetzt funktionierts.
nebenbei: Ist es relativ einfach ein Update auf 5.x durchzuführen (Linux)?
Und ist es für vorhandene SQL 4.x Anweisungen unproblematisch? <- die oben
angesprochene verhält sich ja zum Beispiel anders.

>
> Falls du genau die geposteten Daten und genau die gepostete Query
> verwendet hast, scheint ein Bug in deinem MySQL zu sein. Ein Workaround
> wäre dann, SELECT DISTINCT ... zu schreiben.

hmm. versuche ein update... wenn es unproblematisch ist.

>
> PS: Ich stelle mit Wohlgefallen fest, daß du das zweite Mal richtig
> zitiert hast. Obwohl ich vergessen hatte, dich auf dein Fullquote
> aufmerksam zu machen.
>
Vielen Dank :-)

Re: JOIN Problem. Komplex oder nur zu dumm?

am 06.06.2006 08:43:37 von Axel Schwenke

"Thomas Berg" wrote:

> es war eine 4.0 Version. Nun 5.0.22. Jetzt funktionierts.
> nebenbei: Ist es relativ einfach ein Update auf 5.x durchzuführen (Linux)?
>
> Und ist es für vorhandene SQL 4.x Anweisungen unproblematisch? <- die oben
> angesprochene verhält sich ja zum Beispiel anders.

Du solltest in *jedem* Fall vorher die entsprechenden Kapitel des
Manuals lesen (Update auf 4.1 und 5.0). Gerade zu 4.1 hat sich sehr
viel geändert: Zeichensätze/Collations bis auf Spalten-Level, Rechte,
Paßwort-Hashing.

> hmm. versuche ein update... wenn es unproblematisch ist.

Prinzipiell OK. Aber schau *vorher* ins Handbuch. Z.B. mußt du für
den Wechsel dein PHP, Perl - welcher Client auch immer - gegen das
neue MySQL linken.

Eventuell reicht es ja, auf eine aktuelle 4.0 zu upgraden. Ein Bug
wie dieser sollte auch in 4.0 gefixt sein. Welche Version hast du
denn nun genau?


XL

Re: JOIN Problem. Komplex oder nur zu dumm?

am 06.06.2006 15:33:50 von Thomas Berg

> Eventuell reicht es ja, auf eine aktuelle 4.0 zu upgraden. Ein Bug
> wie dieser sollte auch in 4.0 gefixt sein. Welche Version hast du
> denn nun genau?

MySQL 4.0.15-Max

Re: JOIN Problem. Komplex oder nur zu dumm?

am 06.06.2006 18:23:28 von Axel Schwenke

"Thomas Berg" wrote:
>> Eventuell reicht es ja, auf eine aktuelle 4.0 zu upgraden. Ein Bug
>> wie dieser sollte auch in 4.0 gefixt sein. Welche Version hast du
>> denn nun genau?
>
> MySQL 4.0.15-Max

http://bugs.mysql.com/bug.php?id=20297


XL

Re: JOIN Problem. Komplex oder nur zu dumm?

am 09.06.2006 08:53:21 von Thomas Berg

> http://bugs.mysql.com/bug.php?id=20297
>
Danke für die Information/Recherche.