【问题标题】:How do I eliminate triplicated rows while retaining duplicated rows (SQL server 2016)如何在保留重复行的同时消除重复行(SQL Server 2016)
【发布时间】:2018-03-07 15:39:16
【问题描述】:

我想谨慎地提出我想回答的问题,而不是试图将其提炼到过程中的一个步骤,所以请忍受我的“意识流”风格。我提炼的问题将是标题所暗示的“如何在保留重复行的同时消除三重行(因此无需分组)?”但我会接受在流程的任何步骤都有效的答案以获得什么我想要。使用 SQL Server 2016。

我正在尝试在我们的数据库中查找“零计费电话”。我使用的第一个定义是这段代码

SELECT  

     max([Inbound Call Client Account]) as [account]

      ,convert(date,format(Dateadd(hh,1,[Inbound Call Time]),'dd/MM/yyyy'),103) as [Date]

     ,max([Activation Id]) as [Activation Id]

  FROM [Call_Table]

  where 

  convert(date,format(Dateadd(hh,1,[Inbound Call Time]),'dd/MM/yyyy'),103) >= '2017-09-01'

  and [Chargeable Duration] = 0

  and ([Inbound Connected Call Duration] IS NULL or [Inbound Connected Call Duration] <1)

  and [Inbound Call Type] = 'normal operator call'

  group by [Inbound Call Time]

基本上任何具有零(或最小)持续时间数字的应答呼叫(普通话务员呼叫)。我按入站呼叫时间分组,因为符合定义的每个呼叫都有两行,我想在 SSRS 报告中进行计数,因此每次呼叫只需要一行。

这已经确定了我想要的电话,但它也带回了我不想要的电话。

account   Date             Activation Id
310722  06/09/2017  15CD7A85-084D-4276-BC80-B5369710EC28
310722  06/09/2017  AA145DE5-A278-4181-8EEF-0AFC4B38F2A8
310722  06/09/2017  71413B46-CDC8-41A2-AD3D-2CE88B7C851F
...
310722  14/09/2017  F36E147A-AC39-4441-9472-225FFD56E013
310722  14/09/2017  04372920-DDC4-47DC-8D9E-1E807441CDB3

我知道(从以前的工作中)14 日的电话是真正的 0 计费,而 6 日的电话则不是。所以我研究了一下有什么区别。

SELECT 
      [Inbound Call Client Account]

      ,[Inbound Call Type]


      ,[Chargeable Duration]
      ,[Activation Id]

      ,[Inbound Call Time]

  FROM [Call_Table]

  where [activation id] = '15CD7A85-084D-4276-BC80-B5369710EC28'

  or [activation id] = 'F36E147A-AC39-4441-9472-225FFD56E013'

  or [activation id] = 'AA145DE5-A278-4181-8EEF-0AFC4B38F2A8'

  or [activation id] = '04372920-DDC4-47DC-8D9E-1E807441CDB3' 

  or [activation id] = '71413B46-CDC8-41A2-AD3D-2CE88B7C851F'

生成的

(对我而言)明显的区别特征是误报具有 3 行具有相同激活 ID 的数据。有没有办法将这种区别合并到我的原始查询中,这样它们就不再出现了?但是 14 日真正的肯定是重复的行,所以据我所知,group by 是行不通的。

【问题讨论】:

  • 抱歉。编辑于。

标签: sql sql-server group-by duplicates


【解决方案1】:

我认为使用HAVING 将是最简单的方法。但是为此您应该使用GROUP BY 这个查询对您有帮助吗?

SELECT  

     max([Inbound Call Client Account]) as [account]

      ,convert(date,format(Dateadd(hh,1,[Inbound Call Time]),'dd/MM/yyyy'),103) as [Date]

     ,max([Activation Id]) as [Activation Id]

  FROM [Call_Table]

  where 

  convert(date,format(Dateadd(hh,1,[Inbound Call Time]),'dd/MM/yyyy'),103) >= '2017-09-01'

  and [Chargeable Duration] = 0

  and ([Inbound Connected Call Duration] IS NULL or [Inbound Connected Call Duration] <1)

  and [Inbound Call Type] = 'normal operator call'

  group by [Inbound Call Time],[Activation Id]
  HAVING Count([Activation Id]) < 3

【讨论】:

  • Msg 245, Level 16, State 1, Line 2 将 varchar 值 '03C51B68-F1AA-4400-944A-2778A4BA6154' 转换为数据类型 int 时转换失败。
  • 所以应该按 [Inbound Call Time],Count([Activation Id]) HAVING Count([Activation Id]) 分组
  • Msg 144,Level 15,State 1,Line 22 不能在用于 GROUP BY 子句的 group by 列表的表达式中使用聚合或子查询。 p.s.可以只发布错误消息吗?不想在试图帮助的人面前显得粗鲁
  • 我认为这并不粗鲁,但我是新手,所以我不确定:) 我编辑了查询,你能再检查一次吗
  • 我们的想法是提出可行的解决方案,所以是的,如果解决方案不起作用,发布错误是可以接受的。
【解决方案2】:

您正在寻找的答案是over clause。此外,在未来的发展中,例如尝试让您列 1 个字。 [Inbound Call Client Account] 会变成 Inbound_Call_Client_Account。这将使引用列变得更容易。底部查询将为您获取所有仅一式三份的行,您可以从那里执行任何您喜欢的 CRUD 操作。

SELECT * FROM (
SELECT [Inbound Call Client Account] as [account]
,convert(date,format(Dateadd(hh,1,[Inbound Call Time]),'dd/MM/yyyy'),103) as [Date]
,ROW_NUMBER() OVER(PARTITION BY [Activation Id] ORDER BY [Inbound Call Time] DESC) AS "Row_Number"
  FROM [Call_Table]
      where 
      convert(date,format(Dateadd(hh,1,[Inbound Call Time]),'dd/MM/yyyy'),103) >= '2017-09-01'
      and [Chargeable Duration] = 0
      and ([Inbound Connected Call Duration] IS NULL or [Inbound Connected Call Duration] <1)
      and [Inbound Call Type] = 'normal operator call') AS foo
WHERE foo.row_number = 3

【讨论】:

  • 我认为这是前进的方向,但问题是原始查询中的 where 条件消除了指向误报的重复行。在入站呼叫类型中,三重呼叫中只有 1 个“普通话务员呼叫”。这有点难以解释,但我需要使用从分组查询中的非分组查询中收集的知识。这有意义吗?
  • 当然,如果没有更好地理解数据,我能做的最好的就是去掉 where 子句,让你自己玩。
猜你喜欢
  • 2019-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 2020-07-27
  • 1970-01-01
  • 2023-02-06
  • 1970-01-01
相关资源
最近更新 更多