我有一个名为调查的表格,其中包含组列和主题列
CREATE TABLE survey (
`group` INT NOT NULL,
`subject` VARCHAR(16) NOT NULL,
UNIQUE INDEX (`group`, `subject`)
);
INSERT INTO survey
VALUES
(1, 'sports'),
(1, 'history'),
(2, 'art'),
(2, 'music'),
(3, 'math'),
(3, 'sports'),
(3, 'science')
;
我试图找出一个查询,它将返回不属于同一组的所有主题对。所以从上面的例子中,我希望看到这些对在表中返回:
science - history
science - art
science - music
history - math
sports - art
sports - music
history - art
history - music
因此,查询不应该返回:
sports - history
作为一个例子,因为他们都在第1组。
非常感谢。
答案 0 :(得分:5)
SELECT s1.subject,
s2.subject
FROM survey s1
JOIN survey s2
ON s1.subject < s2.subject
GROUP BY s1.subject,
s2.subject
HAVING COUNT(CASE
WHEN s1.groupid = s2.groupid THEN 1
END) = 0
答案 1 :(得分:4)
样本表
create table Survey(groupid int, subject varchar(100))
insert into Survey select
1, 'sports' union all select
1, 'history' union all select
2, 'art' union all select
2, 'music' union all select
3, 'math' union all select
3, 'sports' union all select
3, 'science'
符合ANSI标准的查询,适用于所有主流RDBMS
select a.subject, b.subject
from (select distinct subject from Survey) A
inner join (select distinct subject from Survey) B on B.subject > A.subject
left join Survey C on C.subject = A.subject
left join Survey D on D.subject = B.subject and D.groupid = C.groupid
where D.groupid is null
order by a.subject, b.subject
答案 2 :(得分:4)
这是一种略有不同的方法:
SELECT *
FROM (SELECT DISTINCT subject FROM yourtable) AS T1
JOIN (SELECT DISTINCT subject FROM yourtable) AS T2
ON T1.subject < T2.subject
WHERE NOT EXISTS
(
SELECT *
FROM yourtable T3
JOIN yourtable T4
ON T3.id = T4.id
WHERE T1.subject = T3.subject
AND T2.subject = T4.subject
)
ORDER BY t1.subject, t2.subject;
答案 3 :(得分:2)
标准方法是使用MINUS
来获取同一组中所有对的补充,但MySQL doesn't support MINUS
。对于MySQL,您可以基于MINUS
运算符和子查询将NOT IN
转换为语句:
SELECT s1.subject, s2.subject
FROM survey AS s1
JOIN survey AS s2
WHERE (s1.subject, s2.subject) NOT IN
(
SELECT s1.subject, s2.subject
FROM survey AS s1
JOIN survey AS s2
ON s1.group = s2.group
)
;
请注意,这可能会产生重复。如果您不想要它们,请使用SELECT DISTINCT
。
使用索引和示例数据,扩展查询计划为:
+----+--------------------+-------+--------+---------------+-------+---------+--------------------+------+----------+---------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+--------------------+-------+--------+---------------+-------+---------+--------------------+------+----------+---------------------------------------------+ | 1 | PRIMARY | s1 | index | NULL | group | 54 | NULL | 7 | 100.00 | Using index; Using temporary | | 1 | PRIMARY | s2 | index | NULL | group | 54 | NULL | 7 | 100.00 | Using where; Using index; Using join buffer | | 2 | DEPENDENT SUBQUERY | s1 | index | group | group | 54 | NULL | 7 | 85.71 | Using where; Using index | | 2 | DEPENDENT SUBQUERY | s2 | eq_ref | group | group | 54 | test.s1.group,func | 1 | 100.00 | Using where; Using index | +----+--------------------+-------+--------+---------------+-------+---------+--------------------+------+----------+---------------------------------------------+
答案 4 :(得分:0)
Select S1.Subject As LeftSubject
, S2.Subject As RightSubject
From SourceData As S1
Join SourceData As S2
On S2.subject > S1.subject
Left Join (
Select S1.groupid
, S1.subject As LeftSubject
, S2.subject As RightSubject
From SourceData As S1
Join SourceData As S2
On S2.groupid = S1.groupid
And S2.subject > S1.subject
) As Z
On Z.groupid = S1.groupid
And Z.LeftSubject = S1.subject
And Z.RightSubject = S2.subject
Where Z.groupid is null
使用outis'元组格式的另一种变体:
Select S1.Subject As LeftSubject
, S2.Subject As RightSubject
From SourceData As S1
Join SourceData As S2
On S2.subject > S1.subject
Where (S1.groupid, S1.subject, S2.subject) Not In (
Select S1.groupid
, S1.subject
, S2.subject
From SourceData As S1
Join SourceData As S2
On S2.groupid = S1.groupid
Where S2.subject > S1.subject
)