简体   繁体   中英

3 table mySQL join with 2 WHERE clauses from the same column - only one working

I'm pulling out a unique 5 digit track id from our cms by matching the artist, track title and mixname stored in SQL with the actual filename of each mp3.

the id i need and the track title are both stored in table1 . artist and mixname are stored within table 3 in the same column, keyed from different intermediary ids in table 2 (attribute_id '17' corresponds to mixname, '18' to artist.)

therefore I figure i need a CASE statement to review the same data twice, but currently, it only processes case 1 or case 2 - never both.

**table1**  
id | title
12345 | My Way

**table2**      
item_id | attribute_id | value_id

12345 | 17 | 54320
12345 | 18 | 54321

**table3**      
id | value_varchar  

54320 | Classic Swing Remix
54321 | Frank Sinatra   

And the actual SQL query:

SELECT table1.id
FROM (table1 LEFT OUTER JOIN table2 on table1.id = table2.item_id)
RIGHT OUTER JOIN table3 on table2.value_id = table3.id
WHERE table1.title = '{$title}'
AND CASE
WHEN table2.attribute_id = '17' THEN table3.value_varchar = '{$mixname}'
WHEN table2.attribute_id = '18' THEN table3.value_varchar = '{$artist}'
END
ORDER BY table1.id DESC

There are some flaws in your SQL statement. First of all: Don't mix Left and Right Outer Joins. It's confusing. Stay with Left Outer Joins - most people are used to these.

You left outer join table2 to table1. Okay so far. You right outer join table3 to, well to what? There is nothing right of it! I guess you mean Left Outer Join here.

But still, table2 and table3 are being outer-joined, so in case you dont find a matching record in these tables, a dummy record is being added where all values are NULL. Then in the WHERE clause you ask for attributes of these tables. They can be NULL. Thus you turn your outer join effectively into an inner join, because you remove all the additional records. Put the criteria in the ON clause, not in the WHERE clause, to make it work.

You can do this using a group by statement with a having clause:

select table1.id
from table1 join
     table2
     on table1.id = table2.item_id join
     table3
     on table2.value_id = table3.id
where table1.title = '{$title}'
group by table1.id
having sum(table2.attribute_id = '17' and table3.value_varchar = '{$mixname}') > 0 and
       sum(table2.attribute_id = '18' and table3.value_varchar = '{$artist}') > 0;

The first condition in the having clause counts the number of rows for attribute 17 that match the mixname. You want at least one, hence the > 0 . The second does the same thing for attribute 18.

I'm not sure why your original query mixed left and right outer joins. That seems unnecessary. You need matching rows in order to get the attributes values anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM