2012-07-11 70 views
1

我有关系代数和改造这个相当复杂查询的SQL麻烦:转换一个复杂的要求转换成SQL查询

我需要从表一连接到表B,其中不存在的所有值匹配表B中的记录,或者存在匹配记录,但匹配记录集没有包含可能的8个总值中的4个中的一个的字段。

数据库是MySQL 5.0 ...对表使用InnoDB引擎。

+1

它很容易。您需要向表A加入表B,查询表B中没有匹配的记录,或者存在匹配记录,但匹配记录集没有包含可能的8个总值中的4个值中的一个的字段。 – Chandu 2012-07-11 00:13:39

+1

你是什么意思,“匹配记录集没有包含可能的8个总值中的4个值中的一个的字段”?可能的值可能在多个字段中,并且有4或8个值要检查吗? – 2012-07-11 00:39:44

+0

对不起,澄清一点:来自A的记录要么在B中没有匹配的记录(我认为这很清楚,每个人都能得到)或者来自A的记录可以在B中具有匹配的记录,但只有匹配的记录不会使用其中一个不需要的值的“状态”字段(如果B中的任何记录A的匹配记录具有不需要的状态之一,则A中的记录需要丢弃) – 2012-07-11 21:38:13

回答

1

我不知道是否有任何真正的性能改进,但另外一个方法是:

SELECT 
    * 
FROM 
    tableA 
WHERE 
    id NOT IN (SELECT id FROM tableB WHERE field1 NOT IN ("value1", "value2")); 
+0

我认为你的双重否定逻辑是错误的。 – dbenham 2012-07-11 01:51:12

+0

你只希望表B中没有可能值的Ids - 你想从A中排除这个集合。然后我的解释和@llion一样,所以我想我们需要OP来澄清。 – 2012-07-11 02:17:03

+0

这实际上是我在与几个人交谈后找到的解决方案。从我刚刚开始编程时,我就有了“子选择是EVIL”的东西,但在这种情况下,查询表现异常出色。 – 2012-07-11 21:41:50

3
Select 
    a.* 
from 
    a 
left join 
    b 
on 
    a.id=b.id 
where 
    b.id is null 
or 
    b.field1 not in ("value1","value2","value3","value4"); 
+0

这不起作用 - 您的查询返回A行如果不存在匹配的B行或者存在至少一个没有禁止值的匹配B行。您的查询允许A行与匹配的B包含禁止值。如果存在至少一个具有禁止值的B行,则OP不需要A行。 (至少这是我如何解释这个问题) – dbenham 2012-07-11 01:31:29

+0

@dbenham:我认为查询匹配OP的描述 - 除了他希望'SELECT *'。 – 2012-07-11 02:17:43

+0

对我来说,关键短语是*“匹配记录集没有...”*。我们只需等待OP澄清。 – dbenham 2012-07-11 02:59:08

0

你的要求是有点不清楚。我的第一个解释是你只需要A列,并且不会超过给定A行的1个实例。

select * from A where not exists (
    select B.id 
    from B 
    where B.id=A.id 
    and B.field in ('badVal1','badVal2','badVal3','badVal4') 
) 

我的第二个解释是要从所有列(A外加入到B),也许在一排的多个实例,如果有乘数b行,只要不存在乙行有禁值。

select * from A 
    left outer join B on A.id=B.id 
where not exists (
       select C.id 
       from B as C 
       where A.id=C.id 
        and C.field in ('badVal1','badVal2','badVal3','badVal4') 
      ) 

这两个查询都可以使用NOT IN而不是相关NOT EXISTS来表示。如果不知道数据,很难知道哪个更快。