简洁地说,如果查询告诉我A重叠B,那么我也不需要它也告诉我B也重叠A,因为它们相互重叠.
所以我试图在sql中使用自联接来选择’DISTINCT’重叠.
为了说明,这里是一个简单的SQL小提琴,我写的是为了显示包含重叠选择(http://sqlfiddle.com/#!9/7af84f/1)
详细地…
假设我有一个名称(char),d1(int),d2(int)的表,其架构如下.这里d1和d2表示某个间隔的开始和结束,该间隔可能与同一个表中的另一个间隔重叠.
CREATE TABLE test (
letter char ,
d1 int ,
d2 int
) ;
鉴于此表,我填写了一些值
INSERT INTO test (letter,d1,d2)
VALUES
('A', 2, 10), -- overlaps C and D
('B', 12, 20), -- overlaps E
('C', 5, 10), -- overlaps A and D
('D', 1, 8), -- overlaps A and C
('E', 13, 15), -- overlaps B
('F', 25, 30); -- doesn't overlap anything
并运行以下查询,该查询使用自联接来正确查找其中一行中的d1和d2与其他行中的d1和d2包含重叠的行.
-- selects all records that overlap in the range d1 - d2 inclusive
-- (excluding the implicit overlap between a record and itself)
-- The results are sorted by letter followed by d1
SELECT
basetable.letter as test_letter,
basetable.d1,
basetable.d2,
overlaptable.letter as overlap_letter,
overlaptable.d1 as overlap_d1,
overlaptable.d2 as overlap_d2
FROM
test as basetable,
test as overlaptable
WHERE
-- there is an inclusive overlap
basetable.d1 <= overlaptable.d2 and basetable.d2 >= overlaptable.d1
AND
-- the row being checked is not itsself
basetable.letter <> overlaptable.letter
AND
basetable.d1 <> overlaptable.d1
AND
basetable.d2 <> overlaptable.d2
ORDER BY
basetable.letter,
basetable.d1
这正确地给了我以下,显示了所有6个版本的重叠,例如左手栏表示A重叠C而另一行显示C重叠A(注意sqlfiddle似乎不理解字段别名所以我的列标题不同)
test_letter d1 d2 overlap_letter overlap_d1 overlap_d2
A 2 10 D 1 8
B 12 20 E 13 15
C 5 10 D 1 8
D 1 8 A 2 10
D 1 8 C 5 10
E 13 15 B 12 20
我的问题是:
如何更改sql以获得四行’DISTINCT’或’单向’重叠?
即这个结果……
test_letter d1 d2 overlap_letter overlap_d1 overlap_d2
A 2 10 D 1 8
A 2 10 C 5 10
B 12 20 E 13 15
C 5 10 D 1 8
例如:
根据以下推理,只显示左侧列中A,B和C的记录的结果
> A(2,10)与D(1,8)和C(5,10)重叠,{显示这两行}
> B(12,20)与E重叠(13,15){显示此行}
> C(5,10)与D(1,8)重叠{显示此行但不显示A(1,10)重叠,因为第2行已显示A和C重叠}
> D(1,8){不要显示我们已经知道的关于A(1,10)和C(5,10)的任何新内容
> E(13,15){不要显示我们已经知道的关于B(12,20)的任何新内容
> F(25,30){由于没有重叠,所以不要显示任何内容}
最佳答案 你可以改变不平等.而且,你还应该使用JOIN:
SELECT basetable.letter as test_letter, basetable.d1, basetable.d2,
overlaptable.letter as overlap_letter, overlaptable.d1 as overlap_d1, overlaptable.d2 as overlap_d2
FROM test basetable JOIN
test overlaptable
ON basetable.d1 <= overlaptable.d2 AND
basetable.d2 >= overlaptable.d1
WHERE basetable.letter < overlaptable.letter -- This is the change
ORDER BY basetable.letter, basetable.d1;