Sql 从记录集中删除重复项(不包括重复条件中的列)
我遇到了一个mssql数据库,有一个SQL查询,比如Sql 从记录集中删除重复项(不包括重复条件中的列),sql,group-by,distinct,Sql,Group By,Distinct,我遇到了一个mssql数据库,有一个SQL查询,比如 SELECT id, type, start, stop, one, two, three, four FROM a UNION ALL SELECT id, type, start, stop, one, two, three, four FROM b UNION ALL SELECT id, type, start, stop, one, two, three, four FROM c ORDER BY type ASC 导致 row
SELECT id, type, start, stop, one, two, three, four
FROM a
UNION ALL
SELECT id, type, start, stop, one, two, three, four
FROM b
UNION ALL
SELECT id, type, start, stop, one, two, three, four
FROM c
ORDER BY type ASC
导致
row | id type start stop one two three four
----+--------------------------------------------------------------
1 | 1 a 2010-01-01 2010-01-31 100 1000 1000 100
2 | 1 a 2010-02-01 2010-12-31 100 500 500 50
3 | 1 b 2010-01-01 2010-01-31 100 NULL NULL 100
4 | 1 b 2010-01-01 2010-12-31 100 NULL NULL 100
5 | 1 c 2010-01-01 2010-01-31 0 NULL NULL 100
6 | 1 c 2010-01-01 2010-12-31 0 NULL NULL 100
然而,我更喜欢以下结果
row | id type start stop one two three four
----+--------------------------------------------------------------
1 | 1 a 2010-01-01 2010-01-31 100 1000 1000 100
2 | 1 a 2010-02-01 2010-12-31 100 500 500 50
4 | 1 b 2010-01-01 2010-12-31 100 NULL NULL 100
6 | 1 c 2010-01-01 2010-12-31 0 NULL NULL 100
也就是说,删除第3行和第5行,因为它们在各个方面都被复制到第4行和第6行,但在停止列中被复制到,而在排除停止列中具有最低值的不幸行将被删除
我怎样才能做到这一点?
我一直在想
SELECT * FROM (
SELECT id, type, start, stop, one, two, three, four
FROM a
UNION ALL
SELECT id, type, start, stop, one, two, three, four
FROM b
UNION ALL
SELECT id, type, start, stop, one, two, three, four
FROM c
ORDER BY type ASC
) AS types
GROUP BY ... HAVING ???
我需要指导,请帮忙
(不,我不能改变任何条件,我必须在给定的情况下工作。)这应该有效:
SELECT
id,
type,
start,
stop,
one,
two,
three,
four
FROM
A T1
LEFT OUTER JOIN A T2 ON
T2.id = T1.id AND
T2.type = T1.type AND
T2.start = T1.start AND
T2.one = T1.one AND
...
T2.stop > T1.stop
WHERE
T2.id IS NULL -- This must be a NOT NULL column for this to work
这假设type列的值与示例中的表名相同。如果表之间可能有重复的行,则需要使用现有的子查询而不是a来执行相同的逻辑。如果我的假设是正确的,则只需将三个UNION ALL查询中的每一个都替换为上述内容,并更改表名
其思想是,如果存在匹配的行,但停止日期较晚,则不希望将该行包括在结果中。使用左外部联接,T2.id为NULL的唯一方式是如果没有这样的匹配,那么我们可以将其包含在结果集中(这就是为什么id必须是非NULL列才能工作的原因)
既然你说你不能改变数据库,我就饶了你,“这个设计太糟糕了”的谴责;) 类似的问题也被提出和回答。例如: 您的情况更简单(如果我正确理解您的问题描述): 您将从a、b和c中选择的内容放在
(…)
的位置。
只需省略orderby
子句即可
或者,如果不是(id,type,start)->(一,二,三,四),而是(id,type,start,stop)->(一,二,三,四)(意味着必须选择其他相应的列)
要最大化(停止)),此查询通常会生成合理的执行计划:
select id, type, start, stop, one, two, three, four
from (...) types
where stop = (select max(stop)
from (...) t2
where t2.id = types.id
and t2.type = types.type
and t2.start = types.start)
但这取决于数据在源表中的分布方式以及存在哪些索引。在某些情况下,来自上面链接的解决方案可能仍然更好
select id, type, start, stop, one, two, three, four
from (...) types
where stop = (select max(stop)
from (...) t2
where t2.id = types.id
and t2.type = types.type
and t2.start = types.start)