SQL:根据记录创建日期和其他条件筛选记录

时间:2017-04-06 09:50:12

标签: sql sql-server

我很难找到一个更好的解决方案来从我的用户调用数据表中选择唯一记录。 我的表结构如下:

SELECT [MarketName],
       [WebsiteName] ,
       [ID] ,
       [UserID],
       [CreationDate],
       [CallDuration],
       [FromPhone] ,
       [ToPhone],
       [IsAnswered],
       [Source]
FROM [dbo].[UserCallData]

此表中有多个条目具有不同且相同的ID。我想在最近3个月内检查[FromPhone]和[ToPhone]是否存在多次,如果是,我想根据[CreationDate]选择包含所有列的第一条记录,将出现次数计为TotalCallCount并将totalCallDuration加起来作为单一记录。如果[FromPhone]和[ToPhone]没有多次出现,我想要选择所有列。我已经能够提出如下的部分查询。但是,如果不包括group by子句,这不会返回所有列,也不会满足我的整个条件。对此的任何帮助都将受到高度赞赏。

select  [FromPhone], 
        MIN([CreationDate]),
        [ToPhone], 
        marketname, 
        count(*) as TotalCallCount , 
        sum(CallDuration) as TotalCallDuration 
from [dbo].[UserCallData]
where  [CreationDate] >= DATEADD(MONTH, -3, GETDATE())
group by  [FromPhone],[ToPhone], marketname 
having count([FromPhone]) > 1 and count([ToPhone]) >1

2 个答案:

答案 0 :(得分:0)

尝试使用ROW_NUMBER()

;with cte as
(
    select *, ROW_NUMBER() OVER(PARTITION BY FromPhone, ToPhone ORDER BY CreationDate) as RN
    from UserCallData
    where CreationDate >= DATEADD(MONTH, -3, GETDATE())
),
cte_totals as
(
    select C1.FromPhone, C1.ToPhone, COUNT(*) as TotalCallCount, SUM(CallDuration) as TotalCallDuration
    from cte C1
    where exists(select * from cte C2 where C1.FromPhone = C2.FromPhone and C1.ToPhone = C2.ToPhone and C2.RN > 1)
    group by C1.FromPhone, C1.ToPhone
)
select C1.*, TotalCallCount, TotalCallDuration
from cte C1
    inner join cte_totals C2 on C1.FromPhone = C2.FromPhone and C1.ToPhone = C2.ToPhone
where C1.RN = 1 

我在这里写了一个查询,所以它可能有一些错误或错误,但主要想法可能很清楚。

答案 1 :(得分:0)

我不完全确定我已经理解了这个问题,但是如果我有以下可能是你想要的(或者是一个有用的起点):

SELECT
       ucd.FromPhone,
       min(ucd.CreationDate) as MinCreationDate,
       ucd.ToPhone,
       ucd.MarketName,
       count(*) as TotalCallCount,
       sum(ucd.CallDuration) as TotalCallDuration,
       case
           when min(ucd.WebsiteName) = max(ucd.WebsiteName) then min(ucd.WebsiteName)
           else '* Various'
       end as WebsiteName,
       case
           when min(ucd.ID) = max(ucd.ID) then min(ucd.ID)
           else '* Various'
       end as ID,
       case
           when min(ucd.UserID) = max(ucd.UserID) then min(ucd.UserID)
           else '* Various'
       end as UserID,
       case
           when min(ucd.IsAnswered) = max(ucd.IsAnswered) then min(ucd.IsAnswered)
           else '* Some'
       end as IsAnswered,
       case
           when min(ucd.Source) = max(ucd.Source) then min(ucd.Source)
           else '* Various'
       end as Source
FROM
    dbo.UserCallData ucd
WHERE
    ucd.CreationDate >= DATEADD(MONTH, -3, GETDATE())
GROUP BY
    ucd.FromPhone,
    ucd.ToPhone,
    ucd.MarketName

我们将行折叠在一起,如果所有行都对给定列达成一致(所以min(Field) = max(Field)),则返回min(Field)值(与其他所有值相同,但避免出现问题)需要额外的“分组依据”条款,这些条款会干扰其他案件)。在他们不同意的地方,我已经返回"* something"

代码假定所有列都是文本类型列(您还没有说过),您可能会遇到转换错误。它还假设这些字段都不是null。如果这些假设不正确,您/我们可以调整代码。如果你不能为自己做这件事,让我知道问题,我会很乐意尽我所能。