【问题标题】:How to select rows based on column value is repeating and has different values in another column如何根据列值选择行重复并且在另一列中具有不同的值
【发布时间】:2015-08-26 07:46:19
【问题描述】:

我需要查询一个表才能返回行,但我无法正确查询该表。这是我的表格视图:

Id  Name    Date        Subject     TrackingToken   RegardingObjectId                       Type    TypeName
1   XXXX    8/26/2015   RE: XXXXXX  CRM:0030062     496BF810-4DBE-E311-9357-00505686395E    112 RE: YYYY
1   XXXX    8/27/2015   RE: XXXXXX  CRM:0030055     AA8C2F71-CDD1-E311-894A-005056863ADA    112 RE: YYYY
1   XXXX    8/28/2015   RE: XXXXXX  CRM:0030055     4DF02C89-2FBE-E311-9357-00505686395E    112 RE: YYYY
1   XXXX    8/29/2015   RE: XXXXXX  CRM:0030049     496BF810-4DBE-E311-9357-00505686395E    112 RE: YYYY
1   XXXX    8/30/2015   RE: XXXXXX  CRM:0030049     06393EF9-71CC-E311-894A-005056863ADA    112 RE: YYYY
1   XXXX    8/31/2015   RE: XXXXXX  CRM:0030047     8BE51823-52BE-E311-9357-00505686395E    112 RE: YYYY
1   XXXX    9/1/2015    RE: XXXXXX  CRM:0030003     6ABE11CA-BABF-E311-89E9-005056863ADA    112 RE: YYYY

结果集应该返回:

Id  Name    Date        Subject     TrackingToken   RegardingObjectId                       Type    TypeName
1   XXXX    8/27/2015   RE: XXXXXX  CRM:0030055     AA8C2F71-CDD1-E311-894A-005056863ADA    112 RE: YYYY
1   XXXX    8/28/2015   RE: XXXXXX  CRM:0030055     4DF02C89-2FBE-E311-9357-00505686395E    112 RE: YYYY
1   XXXX    8/29/2015   RE: XXXXXX  CRM:0030049     496BF810-4DBE-E311-9357-00505686395E    112 RE: YYYY
1   XXXX    8/30/2015   RE: XXXXXX  CRM:0030049     06393EF9-71CC-E311-894A-005056863ADA    112 RE: YYYY

换句话说:选择列 TrackingToken 重复且 AboutObjectId 具有不同值的所有记录。

当前查询:

select [OwnerId],[OwnerIdName],[CreatedOn],[Subject],
[TrackingToken],[RegardingObjectId],
[RegardingObjectTypeCode],[RegardingObjectIdName]

from [TableX].[dbo].[Email] a
where not exists (select [TrackingToken], [RegardingObjectId]
                  from [TableX].[dbo].[Email] b
                  where a.[TrackingToken] = b.[TrackingToken]
                    and a.[RegardingObjectId] = b.[RegardingObjectId]
                    AND RegardingObjectTypeCode = 112
                  group by [TrackingToken],[RegardingObjectId]
                  having count(*)> 1)
  and a.TrackingToken in (select TrackingToken
                          from [TableX].[dbo].[Email]
                          group by TrackingToken
                          having count(*) > 1)
  and a.RegardingObjectId is not null
  and a.RegardingObjectTypeCode = 112
  and a.TrackingToken is not null
order by a.TrackingToken desc

【问题讨论】:

    标签: sql sql-server tsql select


    【解决方案1】:

    您可以使用 COUNT 的分析版本来计算一定范围内的记录(在您的情况下是 TrackingToken)。然后只保留不同 AboutObjectId 的计数大于 1 的记录。

    select *
    from
    (
      select mytable.* 
        , count(distinct regardingobjectid) over (partition by trackingtoken) as cnt
      from mytable
    ) counted
    where cnt > 1;
    

    编辑:正如 Felix Pamittan 指出的那样,SQL Server 不完全支持 COUNT OVER,因此您不能将 DISTINCT 与它一起使用。所以这里和普通的 COUNT 聚合是一样的:

    select mytable.* 
    from mytable
    where 
    (
      select count(distinct token.regardingobjectid) 
      from mytable token
      where token.trackingtoken = mytable.trackingtoken
    ) > 1;
    

    或者没有相关子查询,而是使用派生表:

    select mytable.* 
    from mytable
    join
    (
      select trackingtoken
      from mytable
      group by trackingtoken
      having count(distinct regardingobjectid) > 1
    ) tokens on tokens.trackingtoken = mytable.trackingtoken;
    

    【讨论】:

    • 你能在窗口函数上做COUNT(DISTINCT)吗?
    • @Felix Pamittan:你是对的。令人惊讶的是,SQL Server 不完全支持 COUNT OVER 并且确实缺乏对不同值的计数。 (我通常使用 COUN(DISTINCT) OVER 完美运行的 Oracle。我不知道 SQL Server 可能不会。)
    • 哦,所以它适用于 Oracle。好的。无论如何,我的回答是解决COUNT(DISTINCT) OVER
    • 我添加了两个使用普通聚合计数而不是分析计数的解决方案。这也可以与 EXISTS(相关)或 IN(不相关)一起使用。所以这个问题有很多解决方案。
    【解决方案2】:

    您可以统计[RegardingObjectId]的不同数量:

    select TrackingToken
    from [TableX].[dbo].[Email]
    group by TrackingToken
    having count(distinct [RegardingObjectId]) > 1
    

    【讨论】:

    • 但他在所需结果中有其他列。
    • 我没有用存在和主选择复制整个查询。我只是放了一个内部查询。
    【解决方案3】:

    下面是一个工作示例

    CREATE TABLE #X(Id INT,Name NVARCHAR(8),Date DATE,Subject NVARCHAR(16),TrackingToken NVARCHAR(14),RegardingObjectId UNIQUEIDENTIFIER,Type INT,TypeName NVARCHAR(8))
    
    INSERT INTO #X(Id,Name,Date,Subject,TrackingToken,RegardingObjectId,Type,TypeName)
    VALUES
    (1,'XXXX','8/26/2015','RE: XXXXXX','CRM:0030062','496BF810-4DBE-E311-9357-00505686395E',112,'RE: YYYY'),
    (1,'XXXX','8/27/2015','RE: XXXXXX','CRM:0030055','AA8C2F71-CDD1-E311-894A-005056863ADA',112,'RE: YYYY'),
    (1,'XXXX','8/28/2015','RE: XXXXXX','CRM:0030055','4DF02C89-2FBE-E311-9357-00505686395E',112,'RE: YYYY'),
    (1,'XXXX','8/29/2015','RE: XXXXXX','CRM:0030049','496BF810-4DBE-E311-9357-00505686395E',112,'RE: YYYY'),
    (1,'XXXX','8/30/2015','RE: XXXXXX','CRM:0030049','06393EF9-71CC-E311-894A-005056863ADA',112,'RE: YYYY'),
    (1,'XXXX','8/31/2015','RE: XXXXXX','CRM:0030047','8BE51823-52BE-E311-9357-00505686395E',112,'RE: YYYY'),
    (1,'XXXX','9/1/2015' ,'RE: XXXXXX','CRM:0030003','6ABE11CA-BABF-E311-89E9-005056863ADA',112,'RE: YYYY')
    
    SELECT      A.*
    FROM        #X AS A
    INNER JOIN
        (
            SELECT      TrackingToken
            FROM        #X
            GROUP BY    TrackingToken
            HAVING      COUNT(*) > 1
        ) AS O ON O.TrackingToken = A.TrackingToken
    
    DROP TABLE #X
    

    您可以通过向 TrackingToken 列添加索引来优化这一点

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-17
      • 2022-07-18
      • 1970-01-01
      • 2017-02-14
      • 2015-05-24
      • 2016-02-23
      • 2012-05-25
      • 2019-02-10
      相关资源
      最近更新 更多