代码之家  ›  专栏  ›  技术社区  ›  Novitzky

对多个列进行非重复计数

  •  156
  • Novitzky  · 技术社区  · 17 年前

    有没有更好的方法来执行这样的查询:

    SELECT COUNT(*) 
    FROM (SELECT DISTINCT DocumentId, DocumentSessionId
          FROM DocumentOutputItems) AS internalQuery
    

    我需要从这个表中计算不同项的数目,但是不同项超过了两列。

    我的查询工作正常,但我想知道是否可以只使用一个查询(而不使用子查询)获得最终结果。

    17 回复  |  直到 7 年前
        1
  •  55
  •   THE JOATMON    10 年前

    如果您试图提高性能,可以尝试在两列的哈希值或连接值上创建持久化计算列。

    一旦它被持久化,只要列是确定的,并且您正在使用“健全”的数据库设置,它就可以被索引和/或在上面创建统计信息。

    我相信计算列的一个不同计数将等价于您的查询。

        2
  •  47
  •   JayTee    12 年前

    编辑:从不可靠的仅校验和查询更改 我发现了一种方法(在SQL Server 2005中)可以很好地工作,我可以根据需要使用任意多的列(通过将它们添加到checksum()函数中)。函数的作用是:将ints转换为varchars,使distinct更加可靠。

    SELECT COUNT(DISTINCT (CHECKSUM(DocumentId,DocumentSessionId)) + CHECKSUM(REVERSE(DocumentId),REVERSE(DocumentSessionId)) )
    FROM DocumentOutPutItems
    
        3
  •  22
  •   APC    14 年前

    您不喜欢现有查询的哪些方面?如果你担心的话 DISTINCT 跨两列不返回唯一排列为什么不尝试它?

    它当然可以像您在Oracle中预期的那样工作。

    SQL> select distinct deptno, job from emp
      2  order by deptno, job
      3  /
    
        DEPTNO JOB
    ---------- ---------
            10 CLERK
            10 MANAGER
            10 PRESIDENT
            20 ANALYST
            20 CLERK
            20 MANAGER
            30 CLERK
            30 MANAGER
            30 SALESMAN
    
    9 rows selected.
    
    
    SQL> select count(*) from (
      2  select distinct deptno, job from emp
      3  )
      4  /
    
      COUNT(*)
    ----------
             9
    
    SQL>
    

    编辑

    我对分析学一窍不通,但答案却令人沮丧地显而易见…

    SQL> select count(distinct concat(deptno,job)) from emp
      2  /
    
    COUNT(DISTINCTCONCAT(DEPTNO,JOB))
    ---------------------------------
                                    9
    
    SQL>
    

    编辑2

    考虑到以下数据,上面提供的连接解决方案将计算错误:

    col1  col2
    ----  ----
    A     AA
    AA    A
    

    所以我们要包括一个分隔符…

    select col1 + '*' + col2 from t23
    /
    

    显然,所选分隔符必须是一个字符或一组字符,不能出现在任何列中。

        4
  •  14
  •   Trevor Tippins    17 年前

    比如:

    select count(*)
    from
      (select count(*) cnt
       from DocumentOutputItems
       group by DocumentId, DocumentSessionId) t1
    
    

    可能和你已经做的一样,但是它避免了不同的。

        5
  •  9
  •   spelunk1    10 年前

    要作为单个查询运行,请连接列,然后获取连接字符串实例的独特计数。

    SELECT count(DISTINCT concat(DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
    

    在MySQL中,您可以在不使用串联步骤的情况下执行相同的操作,如下所示:

    SELECT count(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems;
    

    mysql文档中提到了这个特性:

    http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count-distinct

        6
  •  7
  •   starbeamrainbowlabs Trevor    9 年前

    下面是一个较短的版本,没有选择子选项:

    SELECT COUNT(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems
    

    它在MySQL中工作得很好,我认为优化器更容易理解这一点。

    编辑:很明显我误读了mssql和mysql——很抱歉,但也许它还是有帮助的。

        7
  •  4
  •   tehaugmenter    13 年前

    我在搜索我自己的问题时发现了这个,发现如果你计算不同的对象,你会得到正确的返回数字(我使用的是MySQL)

    SELECT COUNT(DISTINCT DocumentID) AS Count1, 
      COUNT(DISTINCT DocumentSessionId) AS Count2
      FROM DocumentOutputItems
    
        8
  •  3
  •   Bliek    17 年前

    您的查询没有问题,但您也可以这样做:

    WITH internalQuery (Amount)
    AS
    (
        SELECT (0)
          FROM DocumentOutputItems
      GROUP BY DocumentId, DocumentSessionId
    )
    SELECT COUNT(*) AS NumberOfDistinctRows
      FROM internalQuery
    
        9
  •  2
  •   KM.    17 年前

    如果只有一个字段“distinct”,则可以使用:

    SELECT COUNT(DISTINCT DocumentId) 
    FROM DocumentOutputItems
    

    这确实会返回与原始查询计划相同的查询计划,正如在set showplan_all打开时测试的那样。但是,您使用了两个字段,因此可以尝试以下疯狂操作:

        SELECT COUNT(DISTINCT convert(varchar(15),DocumentId)+'|~|'+convert(varchar(15), DocumentSessionId)) 
        FROM DocumentOutputItems
    

    但如果涉及空值,则会出现问题。我会坚持最初的问题。

        10
  •  2
  •   Alexander    13 年前

    希望这是我在Prima Vista上写的作品

    SELECT COUNT(*) 
    FROM DocumentOutputItems 
    GROUP BY DocumentId, DocumentSessionId
    
        11
  •  2
  •   karmakaze    8 年前

    很多(大多数?)SQL数据库可以使用类似于值的元组,因此您只需执行以下操作: SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems; 如果您的数据库不支持这一点,可以根据@oncel umut turer对校验和或其他标量函数的建议进行模拟,以提供良好的唯一性,例如。 COUNT(DISTINCT CONCAT(DocumentId, ':', DocumentSessionId)) .

    正在执行元组的相关使用 IN 查询,例如: SELECT * FROM DocumentOutputItems WHERE (DocumentId, DocumentSessionId) in (('a', '1'), ('b', '2'));

        12
  •  1
  •   Community Mohan Dere    9 年前

    我希望MS SQL也可以做类似计数的事情(不同的A、B)。但它不能。

    起初,在一些测试checksum()未能创建唯一值之后,Jaytee的答案似乎是我bu的一个解决方案。一个简单的例子是,校验和(31467519)和校验和(691120823)给出了相同的答案,即55。

    然后我做了一些研究,发现微软不建议使用校验和进行变更检测。在一些论坛中,有些人建议使用

    SELECT COUNT(DISTINCT CHECKSUM(value1, value2, ..., valueN) + CHECKSUM(valueN, value(N-1), ..., value1))
    

    但这也不令人困惑。

    可以按照中的建议使用hashbytes()函数 TSQL CHECKSUM conundrum .然而,这也有很小的机会不返回独特的结果。

    我建议使用

    SELECT COUNT(DISTINCT CAST(DocumentId AS VARCHAR)+'-'+CAST(DocumentSessionId AS VARCHAR)) FROM DocumentOutputItems
    
        13
  •  0
  •   Nata    8 年前

    它对我有用。在Oracle中:

    SELECT SUM(DECODE(COUNT(*),1,1,1))
    FROM DocumentOutputItems GROUP BY DocumentId, DocumentSessionId;
    

    在JPQL中:

    SELECT SUM(CASE WHEN COUNT(i)=1 THEN 1 ELSE 1 END)
    FROM DocumentOutputItems i GROUP BY i.DocumentId, i.DocumentSessionId;
    
        14
  •  0
  •   ADyson    8 年前

    这个怎么样?

    Select DocumentId, DocumentSessionId, count(*) as c 
    from DocumentOutputItems 
    group by DocumentId, DocumentSessionId;
    

    这将使我们获得documentid和documentsessionid的所有可能组合的计数。

        15
  •  0
  •   Nick SamSmith1986    7 年前

    您可以使用count函数两次。

    在这种情况下,应该是:

    SELECT COUNT (DISTINCT DocumentId), COUNT (DISTINCT DocumentSessionId) 
    FROM DocumentOutputItems
    
        16
  •  -1
  •   rishi jain    7 年前

    选择distinct documentid作为i,documentsessionid作为s,count(*)

    来自文档输出项

    按I、S分组;

    此代码对2个参数使用distinct,并提供特定于这些distinct值的行数和行数。这对我很有用 mysql 像一个魅力。

        17
  •  -3
  •   Barry DeCicco    10 年前

    这是在Quora上摆姿势和回答的( https://www.quora.com/In-SQL-how-to-I-count-DISTINCT-over-multiple-columns ):

    select col1, col2, col3, count(*)
    from table
    group by col1, col2, col3
    

    我在sas中处理这个问题,sas proc sql不喜欢distinct中有多个列。