3个表mySQL与来自同一列的2个WHERE子句连接 - 只有一个工作

时间:2014-02-17 16:01:45

标签: php mysql sql join

我通过将存储在SQL中的艺术家,曲目标题和混合名称与每个mp3的实际文件名相匹配,从我们的cms中提取出一个唯一的5位数曲目ID。

我需要的ID和曲目标题都存储在 table1 中。 artist和mixname存储在同一列的表3 中,从表2 中的不同中间ID键入(attribute_id'17'对应mixname,'18'对应艺术家。 )

因此,我认为我需要CASE语句两次审查相同的数据,但目前,它只处理案例1或案例2 - 从不同时处理。

**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   

实际的SQL查询:

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

2 个答案:

答案 0 :(得分:1)

您的SQL语句中存在一些缺陷。首先:不要混合左外连接。这令人困惑。留在左外连接 - 大多数人习惯这些。

您将外连接table2留给table1。好的,到目前为止。你右边连接table3,到底是什么?它没有任何权利!我想你的意思是左外加入。

但是,table2和table3仍然是外部连接的,所以如果你在这些表中找不到匹配的记录,就会添加一个虚拟记录,其中所有值都是NULL。然后在WHERE子句中询问这些表的属性。它们可以为NULL。因此,您可以有效地将外部联接转换为内部联接,因为您删除了所有其他记录。将标准放在ON子句中,而不是在WHERE子句中,以使其起作用。

答案 1 :(得分:1)

您可以使用带有group by子句的having语句执行此操作:

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;

having子句中的第一个条件计算属性17与mixname匹配的行数。你想要至少一个,因此> 0。对于属性18,第二个做同样的事情。

我不确定原始查询为什么混合了左外连接和右外连接。这似乎没必要。您需要匹配行才能获取属性值。