你看到SKU1有两行,但实际上这两行的内容是相同的,只是“b”和“c”的顺序有所不同。
如果我想删除第二张图片中显示的重复行怎么办?
在Oracle中有一个LEAST
/ GREATEST
函数可以实现它,但我使用的是SQL Server,因此它不能按照以下帖子的说明工作:
答案 0 :(得分:1)
如果使用下面的步骤并获得相同的结果,请使用Max()和Min函数而不是最小和最大的oracle。
Create Table Transactions (Name varchar(255),Quantity1 int,Quantity2 int)
Insert Into Transactions values
('SKU1',10,20),
('SKU1',20,10),
('SKU2',10,20),
('SKU2',10,20)
现在我使用下面的查询来找到答案的解决方案
Select T1.Name,MAX(T1.Quantity1),MIN(T2.Quantity2) From Transactions T1
join Transactions T2
on T1.Name=T2.Name
group by T1.Name
请回复
答案 1 :(得分:1)
如果它只有2列,那么订单对于该组来说无关紧要?
然后您可以使用IIF(或CASE WHEN)来计算最大值和最小值 并在GROUP BY中使用这些计算值。
例如:
select Name,
MAX(Val1) as Val1,
MIN(Val2) as Val2
from Table1
GROUP BY Name,
IIF(Val2 is null or Val1 < Val2, Val1, Val2),
IIF(Val1 is null or Val1 < Val2, Val2, Val1);
对于将给出结果的示例记录:
Name Val1 Val2
SKU1 20 10
SKU2 20 10
或者如果你想使用花哨的XML技巧:
select Name, max(Val1) as Val1, min(Val2) as Val2
from (
select *,
cast(
convert(XML,
concat('<n>',Val1,'</n><n>',Val2,'</n>')
).query('for $n in /n order by $n return string($n)'
) as varchar(6)) as SortedValues
from Table1
) q
group by Name, SortedValues;
当涉及更多列时,最后一种方法可能更有用。
实际删除重复项?
这是一个使用表变量来演示的示例:
declare @Table1 TABLE (Id int, Name varchar(20), Val1 int, Val2 int);
Insert Into @Table1 values
(1,'SKU1',10,20),
(2,'SKU1',20,10),
(3,'SKU1',12,15),
(4,'SKU2',10,null),
(5,'SKU2',null,10),
(6,'SKU2',10,20);
delete from @Table1
where Id in (
select Id
from (
select Id,
row_number() over (partition by Name,
IIF(Val2 is null or Val1 < Val2, Val1, Val2),
IIF(Val1 is null or Val1 < Val2, Val2, Val1)
order by Val1 desc, Val2 desc
) as rn
from @Table1
) q
where rn > 1
);
select * from @Table1;
答案 2 :(得分:1)
greatest()
最大(b,c)与:
相同case
when b > c then b
else c
end
您可以将它与不同的一起使用以删除重复项:
select distinct
a,
case when b > c then b else c end as x
from the_table
order by a;
答案 3 :(得分:1)
试试%%physloc%%
。它相当于oracle的RowId
。
找到它
select *, %%physloc%% from [MyTable] where ...
删除您想要的内容
delete from [MyTable] where %%physloc%% = 0xDEADBEEF -- (your address)
考虑添加唯一/主键以防止将来发生。
答案 4 :(得分:1)
SELECT * FROM abc where A='SKU1'and B=20 || A='SKU2'and B=10
a b c
SKU1 20 10
SKU2 10 20
答案 5 :(得分:1)
根据您的问题,您不清楚是按列还是重复过滤重复项。让我描述两者,以确保完全解决您的问题。
在示例1 中,您可以看到我们有重复的行:
要过滤它们,只需在查询中添加关键字 DISTINCT
,如下所示:
SELECT DISTINCT * FROM myTable;
它过滤重复的行并返回:
因此,在这种情况下,您不需要least
或greatest
函数。
在示例2 中,您可以看到我们在列中有重复项:
此处,SELECT DISTINCT * from abc
仍将返回所有4行。
如果我们只考虑过滤中的第一列,则可以通过以下查询来实现:
select distinct t.Col1,
(select top 1 Col2 from myTable ts where t.Col1=ts.Col1) Col2,
(select top 1 Col3 from myTable ts where t.Col1=ts.Col1) Col3
from myTable t
它将在每列中选择第一个匹配值,因此查询结果将为:
示例1与此示例之间的区别在于,它仅消除Col1
myTable
中值的重复出现,然后返回其他列的相关值 - 因此结果为{ {1}}和Col1
不同。
注意:
Col2
,因为那时您将被迫列出select distinct中的列,这将返回您想要的更多行。不幸的是,T-SQL不提供像myTable
这样的东西,即你不能直接指定一个不同的(单个)字段名。具有相同结果的更高级的查询(您可能曾经见过!)具有相同的结果:
SELECT DISTINCT ON(fieldname)
此语句对子查询中Col1上每个值的出现进行编号,然后获取每个重复行中的第一个 - 这实际上是Col1的分组(但没有SELECT Col1, Col2, Col3
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col1) AS RowNumber
FROM myTable
) t
WHERE RowNumber=1
的缺点)。
N.B。在上面的示例中,我假设一个表定义如下:
GROUP BY
对于上面的示例,我们不需要声明主键列。但一般来说,您需要数据库表中的主键才能有效地引用行。
如果要永久删除不需要的行,则应引入主键,因为这样可以删除不易显示的行,如下所示(即它是上面提到的高级查询的逆过滤器):
CREATE TABLE [dbo].[myTable](
[Col1] [nvarchar](max) NULL,
[Col2] [int] NULL,
[Col3] [int] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
这假设您添加了一个自动递增的整数主键DELETE FROM [dbo].[myTable]
WHERE myPK NOT IN
(SELECT myPK
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col1) AS RowNumber
FROM [dbo].[myTable]
) t
WHERE RowNumber=1 and myPK=t.myPK)
(您可以通过使用设计器轻松地通过SQL Management Studio执行此操作)。
或者您可以执行以下查询将其添加到现有表中:
myPK
您可以找到更多示例here at MSDN.
答案 6 :(得分:1)
起初看起来有点复杂,但我们也可以使用PIVOT / UNPIVOT来获得结果
以下是查询
select *
from
(
select
*,
'quantity'+ cast(row_number() over (partition by name order by data) as nvarchar) cols
from
(
select
distinct name, data
from
(select * from transactions)s
unpivot
(
data for cols in (quantity1,quantity2)
)u
)s
)s
pivot
(
max(data) for cols in (quantity1,quantity2)
)p