同一个表上的多个子查询

时间:2015-12-09 22:51:52

标签: sql sql-server

我有两张桌子。一个包含有关对象的详细信息,另一个包含该对象的维度。我想要做的是获得具有一定维度的所有对象。

我已经用这个查询到了一半

SELECT object_key, (SELECT dbo.getDimensionString(object_key)) FROM objectTable 
WHERE object_key IN (SELECT object_key FROM dimensionsTable WHERE value > 90 AND value < 200) 
AND object_key IN (SELECT object_key FROM dimensionsTable WHERE value = 20)
AND object_key IN (SELECT object_key FROM dimensionsTable WHERE value = 10)

只要所有尺寸不同,此代码就可以正常工作。问题是,当我搜索的两个(或更多)维度相同时,它也匹配其他记录。例如,搜索&#39; 100 x 100 x 20&#39;这将匹配像&#39; 100 x 200 x 20&#39;

这样的对象

维度表看起来像这样:

dimension_key, object_key, value
1,1,100
2,1,100
3,1,20

4,2,100
5,2,200
6,2,20

7,3,150
8,3,100
9,3,20

我想搜索结果>&gt; 200&lt; 200,&gt; 90&lt; 200,以及20.结果为1和3

如何更改我的代码以避免这种情况?

2 个答案:

答案 0 :(得分:1)

您可以使用聚合和having子句执行您想要的操作:

select object_key, dbo.getDimensionString(object_key)
from dimensionsTable
where (value > 90 and value < 200) and
      (value = 20) and (value = 10)
group by object_key
having count(*) = 3;

注意count(*) = 3要求值中有三个匹配项。因此,这假设维度表包含每个对象的三个维度。

我应该注意,对于你的最终案例,查询有点不同 - 你不希望100,100,20匹配100,20,20。所以:

select object_key, dbo.getDimensionString(object_key)
from dimensionsTable
where value in (100, 20)
group by object_key
having sum(case when value = 100 then 1 else 0 end) = 2 and
       sum(case when value = 20 then 1 else 0 end) = 1;

这种形式的having子句实际上是更通用的解决方案。

答案 1 :(得分:0)

我想我会在这里发布我的解决方案,以防任何人使用它。

戈登提供的解决方案确实有效,但只要没有任何条件重叠,有时会发生在我的系统中。所以我最终这样做了:

SELECT dimensionsTable.objectTable_key, dbo.getDimensionString(dimensionsTable.objectTable_key) 
FROM (SELECT b.objectTable_key, b.dimension_key 
        FROM(SELECT c.objectTable_key, c.dimension_key 
            FROM(SELECT d.objectTable_key, d.dimension_key 
                    FROM dimensionsTable d WHERE (value >= 100 AND value <= 110)) c 
            JOIN dimensionsTable ON dimensionsTable.objectTable_key = c.objectTable_key  
            WHERE (value >= 100 AND value <= 110) AND dimensionsTable.dimension_key <> c.dimension_key) b
    JOIN dimensionsTable ON dimensionsTable.objectTable_key = b.objectTable_key  
    WHERE (value >= 10 AND value <= 20) AND dimensionsTable.dimension_key <> b.dimension_key) a 
JOIN dimensionsTable ON dimensionsTable.objectTable_key = a.objectTable_key 
WHERE (value >= 210 AND value <= 220) AND dimensionsTable.dimension_key <> a.dimension_key 
GROUP BY dimensionsTable.objectTable_key

如果有人知道更简单的方式来写这个,我会感兴趣:)。