互联网!我对SQL很陌生,我需要在某些字段中获取包含重复信息的所有行,并将它们显示在其他重复项旁边(按重复项分组)。
例如,假设我有一个包含列的表:
A,B,C,D,E,F,G
我希望能够获得所有条目(完整行),其中B,C,D和E与另一个条目共享相同的值,并在原始条目旁边显示重复项。 我已经有了一个解决方案,但效率非常低。我正在努力改善我的运行时间。
我原来的解决方案是:
SELECT TOP 1000
A,
B,
C,
D,
E,
F,
G
FROM tbl_myTable
WHERE (B+C+D+E+F+G) IN (
SELECT
B+C+D+E+F+G
FROM
tbl_myTable
GROUP BY
B,C,D,E,F,G
HAVING COUNT(*) > 1
)
ORDER BY B,C,D,E,F,G ASC
这给了我想要的结果,但它非常缓慢(花了15分钟才能运行)。我使用临时表重写了我的解决方案,并使用此脚本将时间缩短到5分钟的运行时间:
--Drop the temp table if it exists.
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
DROP TABLE #Temp1
SELECT
B+C+D+E+F+G AS CompareString
INTO #Temp1
FROM tbl_myTable
GROUP BY
B,C,D,E,F,G
HAVING COUNT(*) > 1
SELECT TOP 1000
A,
B,
C,
D,
E,
F,
G
FROM tbl_myTable
WHERE (B+C+D+E+F+G) IN (
SELECT * FROM #Temp1
)
ORDER BY B,C,D,E,F,G ASC
五分钟似乎还很长一段时间。有更快的方法吗?我是SQL的新手,所以如果我做的事情不好,请告诉我!谢谢!
答案 0 :(得分:0)
如果没有实际数据,我必须在这里做一些假设。
首先,我假设您的字母字段都是文本类型,并且您使用+来连接而不是添加数值(否则当A = 1 B = 2且C = 3时A + B + C = 6当A = 2 B = 3且C = 1时,这将不匹配)。
接下来我将假设在每一行中都有某种关键字段未在您的示例中显示。像tbl_myTable.MyTableKey bigint IDENTITY(1,1)NOT NULL。
假设这一切,我试试......
SELECT
[BaseTable].MyTableKey AS [Original Record],
[DupCheckTable].MyTableKey AS [Duplicate Record]
FROM
tbl_myTable [BaseTable]
LEFT OUTER JOIN tbl_myTable [DupCheckTable] ON
[BaseTable].A = [DupCheckTable].A
AND
[BaseTable].B = [DupCheckTable].B
AND
--... repeat for each actual field
--AND
[BaseTable].G = [DupCheckTable].G
AND
[BaseTable].MyTableKey < [DupCheckTable].MyTableKey --the less than operator prevents you from getting each match twice
WHERE
[DupCheckTable].MyTableKey IS NOT NULL
我认为这会更快地运行,因为您可以使用表键(可能是索引)作为连接的一部分。此外,您将任何(或我的)查询提供给Tuning Advisor,以查看它认为对统计数据和索引有帮助的内容。
答案 1 :(得分:0)
我会做这样的事情:
with cte as (
SELECT *
, count(*) over (partition by B, C, D, E, F, G) as cnt
, dense_rank() over (order by B, C, D, E, F, G) as grp
FROM STI.[dbo].[tbl_Consignee]
)
select *
from cte
where cnt > 1
order by grp
基本上,dense_rank()
调用为每个唯一元组提供一个标识符(因此您可以使用order by子句将重复项放在彼此旁边),并且计数会计算每个组的行数。