晚上好,
我是SQL的新手。
我一直在努力反转"一个简单的2列关系表。
这是一个解释它的例子:
TABLE KnowEachOther
¦ id_human1 ¦ id_human2 ¦
¦ 1 ¦ 10 ¦
¦ 1 ¦ 11 ¦
¦ 2 ¦ 12 ¦
¦ 2 ¦ 13 ¦
所以我在这里有一张相互认识的人。每一行都意味着humanX和humanY彼此了解。现在我想得到一张彼此不认识的人的表格(假设这张桌子上有所有人)。这样就可以了:
表DontKnowEachOther
¦ id_human1 ¦ id_human2 ¦
¦ 1 ¦ 2 ¦
¦ 1 ¦ 12 ¦
¦ 1 ¦ 13 ¦
¦ 2 ¦ 10 ¦
¦ 2 ¦ 11 ¦
¦ 11 ¦ 10 ¦
¦ 12 ¦ 10 ¦
¦ 13 ¦ 10 ¦
¦ 11 ¦ 12 ¦
¦ 11 ¦ 13 ¦
¦ 12 ¦ 13 ¦
如何做到这一点的任何提示将不胜感激。更值得赞赏的是你如何处理这种非平凡的任务。试图在这里变得更好;)。
非常感谢
答案 0 :(得分:1)
首先,让我们从你忘记的事情开始吧。 (如果你真的不想拥有它,可以从你给出的表中计算出来,但是拥有它肯定会更好。)
CREATE TABLE Humans
(
id int PRIMARY KEY
);
INSERT INTO Humans (id) VALUES (1),(2),(11),(12),(13);
然后,这是你的表和数据:
CREATE TABLE KnowEachOther
(
id1 INT,
id2 INT,
PRIMARY KEY ( id1, id2 )
);
INSERT INTO KnowEachOther (id1, id2) VALUES
(1,10),
(1,11),
(2,12),
(2,13);
然后,我们可以声明以下对所有可能关系的非常有用的视图:
CREATE VIEW AllPossibleRelationships AS SELECT
h1.id AS id1,
h2.id AS id2
FROM Humans AS h1
CROSS JOIN Humans AS h2
WHERE h1.id <> h2.id;
然后,我们可以创建一个视图,从所有可能的关系中删除&#34;那些存在关系的行。 (见WHERE k.id1 IS NULL
)
CREATE VIEW DontKnowEachOther AS SELECT
a.id1 AS id1,
a.id2 AS id2
FROM AllPossibleRelationships AS a
LEFT JOIN KnowEachOther AS k
ON (a.id1 = k.id1 AND a.id2 = k.id2) OR
(a.id1 = k.id2 AND a.id2 = k.id1)
WHERE k.id1 IS NULL
ORDER BY a.id1;
因此,执行SELECT * FROM DontKnowEachOther;
会产生以下结果:
id1 id2
1 2
1 12
1 13
2 1
2 11
11 2
11 12
11 13
12 1
12 11
12 13
13 1
13 11
13 12
注意:对于KnowEachOther
表的内容以及它们对于彼此了解的含义有一些含糊之处。#34;。 &#34;彼此认识&#34;是一种无定向的关系,这意味着如果A知道B,那么B也知道A.鉴于此,你的相互了解&#34; table可以被认为是隐式包含更多行;例如,因为(1,10)有一行,所以暗示了行(10,1)。我的结果考虑了这些隐含的行,并在结果中包含所有隐含和非暗示的行。
过滤掉可能隐含的行作为练习留给读者。
答案 1 :(得分:0)
您需要先获取所有可能的KnowEachOther对,然后选择那些不在KnowEachOther中的对。
由于您没有指定列出所有人的表,因此您需要使用union来组合KnowEachOther中的id_human1和id_human1。通过将结果连接到自身,您将获得所有可能的对。
如果您有一个单独的A = {0,1,0,1}
B = {0,0,1,1}
表,则查询会更简单。
humans
答案 2 :(得分:0)
如果没有单独的Human表,请使用WITH
创建CTE以简化最终SQL的逻辑。
WITH HumanIDs AS
(SELECT
[HumanID]
FROM
(
SELECT id_human1 AS [HumanID] FROM @KnowEachOther
UNION
SELECT id_human2 AS [HumanID] FROM @KnowEachOther
WHERE id_human2 NOT IN (SELECT id_human1 FROM @KnowEachOther)
) x )
然后将HumanIDs加入到一起创建所有可能的对。
然后使用WHERE NOT EXISTS
SELECT DISTINCT
h1.HumanID, h2.HumanID
FROM
HumanIDs AS h1
INNER JOIN HumanIDs AS h2 ON h1.HumanID <> h2.HumanID
WHERE NOT EXISTS
(
SELECT
*
FROM
KnowEachOther AS ke
WHERE
ke.id_human1 = h1.HumanID
AND ke.id_human2 = h2.HumanID
)
ORDER BY
h1.HumanID, h2.HumanID