我正在处理一组本质上属于属性/值对的东西(实际上还有很多东西,但我为了这个问题而简化了)。你可以有效地将这些表格想象如下:
实体(EntityID,AttributeName,AttributeValue)PK = EntityID,AttributeName
目标(TargetID,AttributeName,AttributeValue)PK = TargetID,AttributeName
您如何使用SQL查询EntityID,TargetID的集合,其中Entity具有目标的所有属性以及相应的值?
编辑(根据要求提供DDL):
CREATE TABLE Entities(
EntityID INTEGER NOT NULL,
AttributeName CHAR(50) NOT NULL,
AttributeValue CHAR(50) NOT NULL,
CONSTRAINT EntitiesPK PRIMARY KEY (EntityID,AttributeName)
);
CREATE TABLE Targets(
TargetID INTEGER NOT NULL,
AttributeName CHAR(50) NOT NULL,
AttributeValue CHAR(50) NOT NULL,
CONSTRAINT TargetsPK PRIMARY KEY (TargetID,AttributeName)
);
答案 0 :(得分:0)
我喜欢这些问题,但我认为OP希望至少为表提供创建脚本甚至可能是一些示例数据并不是不合理的。
我喜欢听谁同意谁不同意。
答案 1 :(得分:0)
好的,我想经过多次尝试和编辑后,这个解决方案终于有效了:
SELECT e1.EntityID, t1.TargetID
FROM Entities e1
JOIN Entities e2 ON (e1.EntityID = e2.EntityID)
CROSS JOIN Targets t1
LEFT OUTER JOIN Targets t2 ON (t1.TargetID = t2.TargetID
AND e2.AttributeName = t2.AttributeName
AND e2.AttributeValue = t2.AttributeValue)
GROUP BY e1.EntityID, t1.TargetID
HAVING COUNT(e2.AttributeValue) = COUNT(t2.AttributeValue);
测试数据:
INSERT INTO Entities VALUES
-- exact same attributes, should match
(1, 'Foo1', '123'),
(1, 'Bar1', '123'),
-- same attributes but different values, should not match
(2, 'Foo2', '456'),
(2, 'Bar2', '456'),
-- more columns in Entities, should not match
(3, 'Foo3', '789'),
(3, 'Bar3', '789'),
(3, 'Baz3', '789'),
-- fewer columns in Entities, should match
(4, 'Foo4', '012'),
(4, 'Bar4', '012'),
-- same as case 1, should match Target 1
(5, 'Foo1', '123'),
(5, 'Bar1', '123'),
-- one attribute with different value, should not match
(6, 'A', 'one'),
(6, 'B', 'two');
INSERT INTO Targets VALUES
(1, 'Foo1', '123'),
(1, 'Bar1', '123'),
(2, 'Foo2', 'abc'),
(2, 'Bar2', 'abc'),
(3, 'Foo3', '789'),
(3, 'Bar3', '789'),
(4, 'Foo4', '012'),
(4, 'Bar4', '012'),
(4, 'Baz4', '012'),
(6, 'A', 'one'),
(6, 'B', 'twox');
测试结果:
+----------+----------+
| EntityID | TargetID |
+----------+----------+
| 1 | 1 |
| 4 | 4 |
| 5 | 1 |
+----------+----------+
要回复您的评论,这里是一个反向表格的查询:
SELECT e1.EntityID, t1.TargetID
FROM Targets t1
JOIN Targets t2 ON (t1.TargetID = t2.TargetID)
CROSS JOIN Entities e1
LEFT OUTER JOIN Entities e2 ON (e1.EntityID = e2.EntityID
AND t2.AttributeName = e2.AttributeName
AND t2.AttributeValue = e2.AttributeValue)
GROUP BY e1.EntityID, t1.TargetID
HAVING COUNT(e2.AttributeValue) = COUNT(t2.AttributeValue);
这是输出,给定上面相同的输入数据。
+----------+----------+
| EntityID | TargetID |
+----------+----------+
| 1 | 1 |
| 3 | 3 |
| 5 | 1 |
+----------+----------+
答案 2 :(得分:0)
SELECT *
FROM (
SELECT eo.total,
(
SELECT COUNT(*)
FROM Entities e, Targets t
WHERE e.EntityID = eo.EntityID
AND t.TargetID = e.EntityID
AND t.AttributeName = e.AttributeName
AND t.AttributeValue = e.AttributeValue
) AS equal
FROM (
SELECT e.EntityID, COUNT(*) as total
FROM Entities e
GROUP BY
e.EntityID
) eo
)
WHERE total = equal
答案 3 :(得分:0)
select distinct entityid,targetid
from entities ent
, targets tar
where not exists
( select attributename, AttributeValue
from targets tar2
where tar.targetid = tar2.targetid
minus
select attributename, AttributeValue
from entities ent2
where ent2.entityid = ent.entityid)
and not exists
( select attributename, AttributeValue
from entities ent2
where ent2.entityid = ent.entityid
minus
select attributename, AttributeValue
from targets tar2
where tar.targetid = tar2.targetid)
order by entityid,targetid
/
edit1:
如果目标表中的行在实体表中没有匹配是可以的,则解决方案简化为:
select distinct entityid,targetid
from entities ent
, targets tar
where not exists
( select attributename, AttributeValue
from entities ent2
where ent2.entityid = ent.entityid
minus
select attributename, AttributeValue
from targets tar2
where tar.targetid = tar2.targetid)
order by entityid,targetid
/
编辑2:
要理解OP的确切要求并不容易。
这是一个新的select语句。我希望他会测试我所有的选择陈述以理解差异。我希望他有很好的测试用例并知道他想要什么。
select distinct entityid,targetid
from entities ent
, targets tar
where not exists
( select attributename, AttributeValue
from targets tar2
where tar.targetid = tar2.targetid
minus
select attributename, AttributeValue
from entities ent2
where ent2.entityid = ent.entityid)
order by entityid,targetid
/