Return 列中具有完全相同项目的不同名称对
Return distinct pairs of names which have the same exact items in column
我想在 table 中找到不同的名称对,它们在项目列中具有完全相同的项目。例如:
CREATE TABLE t
(
name VARCHAR(255),
item VARCHAR(255)
);
INSERT INTO t VALUES("Alice", "Orange");
INSERT INTO t VALUES("Alice", "Pear");
INSERT INTO t VALUES("Alice", "Lemon");
INSERT INTO t VALUES("Bob", "Orange");
INSERT INTO t VALUES("Bob", "Pear");
INSERT INTO t VALUES("Bob", "Lemon");
INSERT INTO t VALUES("Charlie", "Pear");
INSERT INTO t VALUES("Charlie", "Lemon");
这里的答案是 Alice,Bob
因为他们拿了完全相同的物品。
我只想用双重否定(使用 NOT EXISTS/NOT IN)来做,我认为这更适合这个问题,但我想不出任何接近的东西功能正常。
这有点类似于 this 问题 但我使用的是 SQLite,所以我不能使用 GROUP_CONCAT() 但我想知道它会怎样使用 NOT EXISTS/NOT IN.
使用关系除法完成
我可能已经找到解决您问题的方法。我的是使用 MySQL 测试的,但它没有使用 GROUP_CONCAT()。它可能适用于您的 SQLite 数据库。我的查询用于查找购买过相同商品的人。
尝试使用这个语句:
SELECT DISTINCT e1.name, e2.name from t e1, t e2 WHERE e1.item=e2.item AND e1.name != e2.name GROUP BY e1.item HAVING count(*) >1;
这似乎适用于 SQLite
select t1.name
from t t1
join t t2 on t1.name <> t2.name and t1.item = t2.item
join (select name, count(*) as cnt from t group by name) t3 on t3.name = t1.name
join (select name, count(*) as cnt from t group by name) t4 on t4.name = t2.name
group by t1.name, t3.cnt, t4.cnt
having count(*) = max(t3.cnt, t4.cnt)
要获取所有名称对之间的共同项目数,您可以使用以下查询:
SELECT t1.name AS name1, t2.name AS name2, COUNT(*) AS cnt
FROM t AS t1
INNER JOIN t AS t2 ON t1.item = t2.item AND t1.name < t2.name
GROUP BY t1.name, t2.name
输出:
name1 name2 cnt
------------------------
Alice Bob 3
Alice Charlie 2
Bob Charlie 2
现在您想要的只是过滤掉计数不等于 name1
和 name2
项数的 (name1, name2)
对。您可以使用带有相关子查询的 HAVING
子句来执行此操作:
SELECT t1.name AS name1, t2.name AS name2
FROM t AS t1
INNER JOIN t AS t2 ON t1.item = t2.item AND t1.name < t2.name
GROUP BY t1.name, t2.name
HAVING COUNT(*) = (SELECT COUNT(*) FROM t WHERE name = t1.name) AND
COUNT(*) = (SELECT COUNT(*) FROM t WHERE name = t2.name)
SELECT t1.name, t2.name
FROM t AS t1, t AS t2
GROUP BY t1.name, t2.name
HAVING t1.name < t2.name
AND NOT EXISTS (SELECT item FROM t WHERE name = t1.name
EXCEPT
SELECT item FROM t WHERE name = t2.name)
AND NOT EXISTS (SELECT item FROM t WHERE name = t2.name
EXCEPT
SELECT item FROM t WHERE name = t1.name);
可以使用 NOT IN,bit 表达完全相同的机制,但更复杂:
SELECT t1.name, t2.name
FROM t AS t1, t AS t2
GROUP BY t1.name, t2.name
HAVING t1.name < t2.name
AND NOT EXISTS (SELECT item
FROM t
WHERE name = t1.name
AND item NOT IN (SELECT item
FROM t
WHERE name = t2.name))
AND NOT EXISTS (SELECT item
FROM t
WHERE name = t2.name
AND item NOT IN (SELECT item
FROM t
WHERE name = t1.name));
我想在 table 中找到不同的名称对,它们在项目列中具有完全相同的项目。例如:
CREATE TABLE t
(
name VARCHAR(255),
item VARCHAR(255)
);
INSERT INTO t VALUES("Alice", "Orange");
INSERT INTO t VALUES("Alice", "Pear");
INSERT INTO t VALUES("Alice", "Lemon");
INSERT INTO t VALUES("Bob", "Orange");
INSERT INTO t VALUES("Bob", "Pear");
INSERT INTO t VALUES("Bob", "Lemon");
INSERT INTO t VALUES("Charlie", "Pear");
INSERT INTO t VALUES("Charlie", "Lemon");
这里的答案是 Alice,Bob
因为他们拿了完全相同的物品。
我只想用双重否定(使用 NOT EXISTS/NOT IN)来做,我认为这更适合这个问题,但我想不出任何接近的东西功能正常。
这有点类似于 this 问题 但我使用的是 SQLite,所以我不能使用 GROUP_CONCAT() 但我想知道它会怎样使用 NOT EXISTS/NOT IN.
我可能已经找到解决您问题的方法。我的是使用 MySQL 测试的,但它没有使用 GROUP_CONCAT()。它可能适用于您的 SQLite 数据库。我的查询用于查找购买过相同商品的人。
尝试使用这个语句:
SELECT DISTINCT e1.name, e2.name from t e1, t e2 WHERE e1.item=e2.item AND e1.name != e2.name GROUP BY e1.item HAVING count(*) >1;
这似乎适用于 SQLite
select t1.name
from t t1
join t t2 on t1.name <> t2.name and t1.item = t2.item
join (select name, count(*) as cnt from t group by name) t3 on t3.name = t1.name
join (select name, count(*) as cnt from t group by name) t4 on t4.name = t2.name
group by t1.name, t3.cnt, t4.cnt
having count(*) = max(t3.cnt, t4.cnt)
要获取所有名称对之间的共同项目数,您可以使用以下查询:
SELECT t1.name AS name1, t2.name AS name2, COUNT(*) AS cnt
FROM t AS t1
INNER JOIN t AS t2 ON t1.item = t2.item AND t1.name < t2.name
GROUP BY t1.name, t2.name
输出:
name1 name2 cnt
------------------------
Alice Bob 3
Alice Charlie 2
Bob Charlie 2
现在您想要的只是过滤掉计数不等于 name1
和 name2
项数的 (name1, name2)
对。您可以使用带有相关子查询的 HAVING
子句来执行此操作:
SELECT t1.name AS name1, t2.name AS name2
FROM t AS t1
INNER JOIN t AS t2 ON t1.item = t2.item AND t1.name < t2.name
GROUP BY t1.name, t2.name
HAVING COUNT(*) = (SELECT COUNT(*) FROM t WHERE name = t1.name) AND
COUNT(*) = (SELECT COUNT(*) FROM t WHERE name = t2.name)
SELECT t1.name, t2.name
FROM t AS t1, t AS t2
GROUP BY t1.name, t2.name
HAVING t1.name < t2.name
AND NOT EXISTS (SELECT item FROM t WHERE name = t1.name
EXCEPT
SELECT item FROM t WHERE name = t2.name)
AND NOT EXISTS (SELECT item FROM t WHERE name = t2.name
EXCEPT
SELECT item FROM t WHERE name = t1.name);
可以使用 NOT IN,bit 表达完全相同的机制,但更复杂:
SELECT t1.name, t2.name
FROM t AS t1, t AS t2
GROUP BY t1.name, t2.name
HAVING t1.name < t2.name
AND NOT EXISTS (SELECT item
FROM t
WHERE name = t1.name
AND item NOT IN (SELECT item
FROM t
WHERE name = t2.name))
AND NOT EXISTS (SELECT item
FROM t
WHERE name = t2.name
AND item NOT IN (SELECT item
FROM t
WHERE name = t1.name));