我的数据库表(DWInfo)是这样的:
InstanceID | AttributeID
1 | 1
1 | 2
1 | 3
2 | 1
2 | 4
3 | 1
3 | 2
有几个实例,每个实例都有多个属性。我想要实现的是:对于给定的id集/规则,我想要获得违反条件的所有InstanceID,例如,让给定的id为1和2,这意味着如果有一个AttributeID=1的实例,Attribute=2也应该存在。在这种情况下,结果将是实例2,因为该实例违反了条件。
我尝试了join,但这似乎只对2个属性有效,而不是更多。
Select * from DWInfo dw1 INNER JOIN DWInfo dw2 ON dw1.InstanceID = dw2.InstanceID where dw1.AttributeID != dw2.AttributeID and dw1.AttributeID = 1 AND dw2.AttributeID != 2
有可能用SQL查询来解决这个问题吗?
假设每个InstanceId
只能有一个不同的AttributeId
,即唯一的复合索引(InstanceId, AttributeId)
:
SELECT InstanceID
FROM DWInfo
WHERE AttributeID IN (1,2)
GROUP BY InstanceID
HAVING SUM(AttributeId = 1) = 1
AND COUNT(*) < 2 /* Or SUM(AttributeId = 2) = 0 */
SQLFiddle演示请注意,如果AttributeId为2意味着实例也需要AttributeId为1 ..逻辑略有不同,这里更简洁:
SELECT InstanceID
FROM DWInfo
WHERE AttributeID IN (1,2)
GROUP BY InstanceID
HAVING COUNT(*) < 2
有属性1的,找到没有属性2的
select InstanceID
from DWInfo
group by InstanceID
having
count(case when AttributeID = 1 then 1 end) > 0
and count(case when AttributeID = 2 then 1 end) = 0
这个答案和地球的基本相同。您可能会发现过滤where
子句中的Attributes是有益的,但这并不是严格必要的。我更喜欢使用case
表达式的标准语法,尽管如果它是可移植的,这种简写会很方便。在这些场景中,我也更喜欢count
而不是sum
。
不清楚是否可以有重复(可能不能),也不清楚属性2是否可以单独出现。您可能需要稍微调整一下数字,但您应该能够遵循模式。
我认为这是你想要的:
select instanceid
from dwinfo
where attributeid in (1, 2)
group by instanceid
having count(*) = 2;
这保证了每个实例有两个匹配的行。如果可以有重复项,则使用:
having count(distinct attributeid) = 2
编辑:对于条件版本(如果1 -> 2):
having max(attributeid = 2) > 0
也就是说,如果它有1或2,那么它必须有2,然后一切都可以。