2012-03-27 36 views
3

我有两个表。我怎样才能让一个WHERE子句仅适用于右表在左加入?

TableA: field_definitions 
field_id, field_type, field_length, field_name, field_desc, display_order, field_section, active 

TableB: user_data 
response_id, user_id, field_id, user_response 

我需要一个查询,从表一返回所有行,如果存在的话,基于特定的user_id匹配从表B中的行。

这里是我迄今为止...

SELECT field_definitions. * , user_data.user_response 
FROM field_definitions 
LEFT JOIN user_data 
USING (field_id) 
WHERE (
user_data.user_id =8 
OR user_data.user_id IS NULL 
) 
AND field_definitions.field_section =1 
AND field_definitions.active =1 
ORDER BY display_order ASC 

这只能如果表B中的行数为零或匹配行的WHERE子句中的USER_ID。如果表B具有匹配field_id但不包含user_id的行,则返回的行数为零。

本质上,一旦在表B中的行对用户X存在,所述查询不再从表A中搜索使用者z的反应和没有时发现返回行。

我需要的结果总是包含从表格中的行,即使有B中没有匹配的行用正确的USER_ID。

+0

你的规格是不明确的。目前不考虑表B,是否希望:a)返回表A中的所有行; b)基于特定的user_id返回表A中的所有行; c)别的东西? – onedaywhen 2012-03-27 07:29:34

+0

@onedaywhen我认为最后一段总结了它,我总是希望从A返回的行和可选地匹配B行的条件,他们是为正确的用户 – Corey 2012-03-27 14:24:18

回答

10

可以移动从WHERE条款这些约束到ON条款(这首先要求你改变USING条款为ON条款:ON条款比USING条款更灵活)。因此:

SELECT field_definitions.*, 
     user_data.user_response 
    FROM field_definitions 
    LEFT 
    JOIN user_data 
    ON user_data.field_id = field_definitions.field_id 
    AND user_data.user_id = 8 
WHERE field_definitions.field_section = 1 
    AND field_definitions.active = 1 
ORDER 
    BY field_definitions.display_order ASC 
; 
3

从概念上讲,首先执行连接,然后将where子句应用于虚拟结果集。如果你想先过滤一个表,你必须代码为内子选择加入。沿着这些路线的东西:

SELECT 
    field_definitions. * , 
    user8.user_response 
FROM 
    field_definitions 
    LEFT JOIN (select * from user_data where user_id=8 or user_id is null) as user8 
    USING (field_id) 
WHERE 
    field_definitions.field_section =1 
    AND field_definitions.active =1 
ORDER BY display_order ASC 
+0

我得到“#1248 - 每个派生表必须有它自己的别名“与此 – Corey 2012-03-27 14:26:16

+0

我忘了包括一个表别名...答复编辑。 – 2012-03-27 18:27:25

1

你可以在里面移动在WHERE子句如下

SELECT field_definitions. * , user_data.user_response 
FROM (
    select * from 
    field_definitions 
    WHERE field_definitions.field_section =1 
    AND field_definitions.active =1) as field_definitions 
LEFT JOIN (
    select * from 
    user_data 
    where user_data.user_id =8 
    OR user_data.user_id IS NULL) as user_data 
USING (field_id) 
ORDER BY display_order ASC 
0

的SEPC的直译:

SELECT field_definitions. * , '{{MISSING}}' AS user_response 
    FROM field_definitions 
UNION 
SELECT field_definitions. * , user_data.user_response 
    FROM field_definitions 
     NATURAL JOIN user_data 
WHERE user_data.user_id = 8; 

不过,我怀疑你不真的很想“表A的所有行”。

相关问题