Sql server 如何比较同一SQL表的多行

Sql server 如何比较同一SQL表的多行,sql-server,Sql Server,假设我有一个SQL Server表,如下所示: id valA valB valC ----------------------- 1 1 2 3 2 4 5 6 3 7 8 9 3 10 11 12 4 13 14 15 4 16 14 15 select * from ( select t.*,

假设我有一个SQL Server表,如下所示:

id   valA   valB   valC
-----------------------
1    1      2      3
2    4      5      6
3    7      8      9
3    10     11     12
4    13     14     15
4    16     14     15
select
    *
from (
    select
        t.*,
        count(*) over (partition by id, valb, valc) cnt
    from t
) t where cnt > 1;
我想比较行,找出那些数据匹配的行。在本例中,我希望标识具有匹配id、valB和valC的行,因此它应该只找到最后两行。valA列的内容将被忽略

然后我想删除两行中的一行,然后根据需要调整valA列。我的问题是识别匹配的行

从这个网站上的许多其他类似问题中,我尝试了各种类似的方法:

SELECT DISTINCT 
    A.id
FROM
    newtable A
INNER JOIN 
    newtable B ON A.id = B.id
WHERE
    A.valB = B.valB AND
    A.valC = B.valC

但我最终得到了四个身份证。我不知道为什么。即使这样做有效,我仍然不确定如何继续对找到的所有匹配行执行更新和删除操作。有什么建议吗?谢谢。

我想你很接近了。您只需排除不需要的行:

SELECT DISTINCT A.id
FROM newtable A INNER JOIN
     newtable B
     ON A.id = B.id
WHERE A.valB = B.valB AND
      A.valC = B.valC AND
      A.valA <> B.valA;
选择不同的A.id
从newtable到内部联接
新表B
在A.id=B.id上
其中A.valB=B.valB和
A.valC=B.valC和
A.valA B.valA;
您也可以使用。如果您有这些类型的查询,许多索引
HASHBYTES
列将有助于比较

或者你可以用DenseRank

;With cte
as
(
select *,
dense_rank() over (  order by id,valb,valc) as rownum
from #temp
)
select * from cte where rownum>1

如果您只需要至少有两行具有相同valb和valc的id,您可以使用:

select distinct 
    id
from t
group by
    id, valb, valc
having count(*) > 1;
;with x as (

select *, count(*) over (partition by id, valb, valc) as N from YourTable

)


-- matching values
select x.id, x.vala, x.valb, x.valc from x where x.N > 1
如果还需要获取其他列,可以使用如下窗口函数
count

id   valA   valB   valC
-----------------------
1    1      2      3
2    4      5      6
3    7      8      9
3    10     11     12
4    13     14     15
4    16     14     15
select
    *
from (
    select
        t.*,
        count(*) over (partition by id, valb, valc) cnt
    from t
) t where cnt > 1;
。。。我的问题是识别匹配的行

要选择匹配的行,请使用以下命令:

select distinct 
    id
from t
group by
    id, valb, valc
having count(*) > 1;
;with x as (

select *, count(*) over (partition by id, valb, valc) as N from YourTable

)


-- matching values
select x.id, x.vala, x.valb, x.valc from x where x.N > 1
…我仍然不确定如何继续更新和删除操作

我建议先做一个选择,然后再查看要删除的内容


小提琴选择比赛:

从以下位置删除:

包括原始表中记录的行号(按Id排序):


告诉你的需求lil更多,比如你将通过什么参数等等

你可以试试这个

declare @t table(id int,valA int,valB int,valC int)
insert into @t values
(1  ,  1   ,   2   ,   3 )
,(2  ,  4   ,   5   ,   6 )
,(3  ,  7   ,   8   ,   9 )
,(3  ,  10  ,   11  ,   12)
,(4  ,  13  ,   14  ,   15)
,(4  ,  16  ,   14  ,   15)

;With CTE as
(
select * ,row_number()over(partition by id,valb,valc order by id)rn
from @t
)
,CTE1 as
(
select * from cte   
where rn>1
)
select * from @t t
where EXISTS(
select id from cte1 c where t.id=c.id)

谢谢,好主意。MSSQL在第一个示例中抱怨CONCAT。第二个示例运行了,但生成了整个表,只是按id排序。谢谢,我现在理解了为什么所有行都出现了,因为它正在查找给定行和另一个(相同)表中的同一行之间的匹配。添加现有内容的问题是,valA内容有时可能会匹配。我想我可以通过在表中有一个唯一的id字段来解决这个问题。@AngeloQ。是的,一个唯一的id可以解决我在
valA
上通过比较试图解决的问题。第一个关于group的示例是一个好主意,只要SELECT包含group BY中的列,否则它会给我一个错误。不过,我也许可以处理这个问题。第二个示例对我不起作用,可能是语法错误?我试图修复它,但无法。谢谢,这似乎对我最有效。不过,我从MSSQL Server 2005中得到了这个错误:“不支持OVER SQL构造或语句。”但它仍然运行,似乎给出了预期的结果。另外,我如何获取行号,或者用什么其他方法最容易返回到原始表中的该行。事实上,我发现我不能简单地删除第二行,直到我第一次将这两行合并在一起。在删除第二行之前,我需要检查valA(和其他列)的内容并复制值。您将传递什么参数?