>Description:
I wanted to get the rows from table Health for which no match exists in the
table resulting from the inner join of Object and NMID.
I ran these queries in MySQL 3.23 and 4.0 with the same incorrect results.
They all work fine on MS SQL Server 2000 and on DB2 7.2.
With a DBMS supporting subqueries, I would have expressed it like this:
1)
SELECT DISTINCT
H.Appliance_ID, H.Health_NMID, H.Health_DeviceOrPort
FROM
Health H
WHERE
NOT EXISTS (SELECT 0
FROM
Object O
INNER JOIN NMID N
ON O.Object_ID = N.Object_ID
WHERE
H.Appliance_ID = N.Appliance_ID
AND H.Health_NMID = N.NMID_NMID
AND H.Health_DeviceOrPOrt = O.Object_Table
)
AND H.Appliance_ID = 0;
Because MySQL lacks support for subqueries,
I tried this SQL-92 compliant form of outer join, but MySQL reject it
with a syntax error.
2)
SELECT DISTINCT
H.Appliance_ID, H.Health_NMID, H.Health_DeviceOrPort
FROM
Health H
LEFT OUTER JOIN Object O
INNER JOIN NMID N
ON O.Object_ID = N.Object_ID
ON H.Appliance_ID = N.Appliance_ID
AND H.Health_DeviceOrPOrt = O.Object_Table
AND H.Health_NMID = N.NMID_NMID
WHERE
H.Appliance_ID = 0
AND N.Object_ID IS NULL;
With a right outer join, no syntax errors is generated but the result is
incorrect.
3)
SELECT DISTINCT
H.Appliance_ID, H.Health_NMID, H.Health_DeviceOrPort
FROM
Object O
INNER JOIN NMID N
ON O.Object_ID = N.Object_ID
RIGHT OUTER JOIN Health H
ON H.Appliance_ID = N.Appliance_ID
AND H.Health_NMID = N.NMID_NMID
AND H.Health_DeviceOrPOrt = O.Object_Table
WHERE
H.Appliance_ID = 0
AND O.Object_ID IS NULL;
This incorrectly returns no rows.
With MS SQL Server 2000 and DB2 v7.2 it makes no difference to test
O.Object_ID IS NULL
or N.Object_ID IS NULL, but with MySQL, it does but in both cases the result
is wrong.
Testing N.Object_ID incorrectly returns 4 rows:
+--------------+-------------+---------------------+
| Appliance_ID | Health_NMID | Health_DeviceOrPort |
+--------------+-------------+---------------------+
| 0 | 1 | device |
| 0 | 2 | device |
| 0 | 3 | device |
| 0 | 4 | device |
+--------------+-------------+---------------------+
Adding parenthesis to force the inner join to be done before the outer join
didn't fix the problem.
4)
SELECT DISTINCT
H.Appliance_ID, H.Health_NMID, H.Health_DeviceOrPort
FROM
-- (Object O
Object O
INNER JOIN NMID N
-- ON O.Object_ID = N.Object_ID)
ON O.Object_ID = N.Object_ID
RIGHT OUTER JOIN Health H
ON H.Appliance_ID = N.Appliance_ID
AND H.Health_NMID = N.NMID_NMID
AND H.Health_DeviceOrPOrt = O.Object_Table
WHERE
H.Appliance_ID = 0
AND O.Object_ID IS NULL;
>How-To-Repeat:
CREATE TABLE Object (Object_ID INTEGER NOT NULL, Object_Table VARCHAR(6) NOT
NULL);
CREATE TABLE NMID (Appliance_ID INTEGER NOT NULL, NMID_NMID INTEGER,
Object_ID INTEGER NOT NULL);
CREATE TABLE Health (Appliance_ID INTEGER NOT NULL, Health_NMID INTEGER NOT
NULL, Health_DeviceOrPort VARCHAR(6) NOT NULL);
INSERT INTO Object(Object_ID, Object_Table) VALUES (101,'Device');
INSERT INTO Object(Object_ID, Object_Table) VALUES (201,'Device');
INSERT INTO Object(Object_ID, Object_Table) VALUES (202,'Port');
INSERT INTO Object(Object_ID, Object_Table) VALUES (302,'Port');
INSERT INTO NMID (Appliance_ID, NMID_NMID, Object_ID) VALUES (0, 1, 101);
INSERT INTO NMID (Appliance_ID, NMID_NMID, Object_ID) VALUES (0, 2, 201);
INSERT INTO NMID (Appliance_ID, NMID_NMID, Object_ID) VALUES (0, 2, 202);
INSERT INTO NMID (Appliance_ID, NMID_NMID, Object_ID) VALUES (0, 3, 302);
INSERT INTO Health (Appliance_ID, Health_NMID, Health_DeviceOrPort) VALUES
(0, 1, 'Device');
INSERT INTO Health (Appliance_ID, Health_NMID, Health_DeviceOrPort) VALUES
(0, 2, 'Device');
INSERT INTO Health (Appliance_ID, Health_NMID, Health_DeviceOrPort) VALUES
(0, 3, 'Device');
INSERT INTO Health (Appliance_ID, Health_NMID, Health_DeviceOrPort) VALUES
(0, 4, 'Device');
The following 2 rows should be returned
Appliance_ID Health_NMID Health_DeviceOrPort
------------ ----------- -------------------
0 3 Device
0 4 Device
>Fix:
Create a temporary table with the result of the inner join
and then use the temporary table in an outer join
>Submitter-Id: Jean-Pierre Pelletier
>Originator: root
>Organization: Peregrine Systems, Inc.
>MySQL support: [none | licence | email support | extended email support ]
>Synopsis: MySQL Bug: Outer Joins producing incorrect result on a single
join referencing multiple tables
>Severity: serious
>Priority: medium
>Category: mysql
>Class: sw-bug
>Release: mysql-4.0.3-beta (Source distribution)
>Server: /usr/mysql/bin/mysqladmin Ver 8.37 Distrib 4.0.3-beta, for
pc-linux-gnu on i686
Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license
Server version 4.0.3-beta
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /tmp/mysql.sock
Uptime: 11 days 15 min 14 sec
Threads: 1 Questions: 440 Slow queries: 0 Opens: 16 Flush tables: 1
Open tables: 10 Queries per second avg: 0.000
>Environment:
<machine, os, target, libraries (multiple lines)>
System: Linux warez.reboot.loran.com 2.4.18 #1 Mon Feb 25 15:35:43 EST 2002
i686 unknown
Architecture: i686
Some paths: /usr/bin/perl /usr/bin/make /usr/bin/gcc /usr/bin/cc
GCC: Reading specs from /usr/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/specs
gcc version 2.95.3 20010315 (release)
Compilation info: CC='gcc' CFLAGS='' CXX='g++' CXXFLAGS='' LDFLAGS=''
LIBC:
lrwxrwxrwx 1 root root 13 Apr 3 10:19 /lib/libc.so.6 ->
libc-2.2.3.so
-rwxr-xr-x 1 root root 1193256 Sep 26 2001 /lib/libc-2.2.3.so
-rw-r--r-- 1 root root 24962644 Apr 4 12:14 /usr/lib/libc.a
-rw-r--r-- 1 root root 190 Aug 31 2001 /usr/lib/libc.so
Configure command: ./configure --prefix=/usr/local/mysql
---------------------------------------------------------------------
Before posting, please check:
http://www.mysql.com/manual.php (the manual)
http://lists.mysql.com/ (the list archive)
To request this thread, e-mail <[EMAIL PROTECTED]>
To unsubscribe, e-mail <[EMAIL PROTECTED]>
Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php