【问题标题】:oracle query to count occurrences in multiple columnsoracle查询以计算多列中的出现次数
【发布时间】:2018-03-17 12:58:23
【问题描述】:

我想根据三列检索总共进行了至少 2 笔交易的客户。 Y - 成功交易

前:

Customer_Name  Col1    Col2    Col3
Customer1        Y       Y      N
Customer2        N       N      Y
Customer3        Y       Y      N

对于上表,我想显示如下输出(想排除只做了一次交易的客户)

Customer1 - 2
Customer3 - 2

【问题讨论】:

  • 表格中每个客户只有一行?
  • 谢谢你 ji..super.
  • 这应该是我问题的答案吗? u = you, ji = kind of => “谢谢你的超级”?请再试一次;我的问题并不难回答;是或否就足够了。您显示的表格显示每个客户一条记录,但您标记了GROUP BY,这表明对多行进行聚合。再说一遍:表中每个客户是否只有一行?
  • 您使用的是什么版本的 Oracle?

标签: oracle group-by count


【解决方案1】:

我看到有两个人使用汇总示例回答了您的问题。因为它们都使用 GROUP BY 和 HAVING 子句。您不一定需要使用任何类型的分组来在此处获得所需的输出。请参阅下面的替代解决方案。这可能只是一种意见,但我更喜欢这种解决方案:

WITH demo_data (cname, col1, col2, col3) AS
( /* Using CTE to produce fake table with data */
  SELECT 'cust1', 'Y', 'Y', 'N' FROM dual UNION ALL
  SELECT 'cust2', 'N', 'N', 'Y' FROM dual UNION ALL
  SELECT 'cust3', 'Y', 'N', 'Y' FROM dual UNION ALL
  SELECT 'cust4', 'Y', 'Y', 'Y' FROM dual UNION ALL
  SELECT 'cust5', 'Y', 'Y', 'N' FROM dual UNION ALL
  SELECT 'cust6', 'Y', 'N', 'N' FROM dual
)
, transform_data AS
( /* Using decode to convert all 'Y' and 'N' to numbers */
  SELECT cname
       , decode(col1, 'Y', 1, 0) AS col1
       , decode(col2, 'Y', 1, 0) AS col2
       , decode(col3, 'Y', 1, 0) AS col3
  FROM demo_data
)
/* Now we created our SUM column using the columns 1 thru 3 */
SELECT cname, col1, col2, col3
  /* I didn't need to create the sum_col however I added it for visual purposes */
  , col1 + col2 + col3 AS sum_col
FROM transform_data
WHERE col1 + col2 + col3 > 1
;

WITH 子句生成的每个表的输出和实际所需输出的屏幕截图。

【讨论】:

    【解决方案2】:

    您可以结合 SUM() 和 HAVING() 子句。

    SELECT Customer_Name,
    SUM(CASE WHEN Col1='Y' then 1 else 0 end)+
    SUM(CASE WHEN Col2='Y' then 1 else 0 end)+
    SUM(CASE WHEN Col3='Y' then 1 else 0 end) as total
    FROM myTable
    GROUP BY Customer_Name
    HAVING SUM(CASE WHEN Col1='Y' then 1 else 0 end)+
    SUM(CASE WHEN Col2='Y' then 1 else 0 end)+
    SUM(CASE WHEN Col3='Y' then 1 else 0 end)=2
    
        Result:
        CUSTOMER_NAME   TOTAL
        Customer3        2
        Customer1        2
    

    【讨论】:

      【解决方案3】:

      有点类似于 @anonyXmous 的代码,但使用的是 DECODE 而不是那么多(不必要的?)SUM:

      SQL> with test (cname, col1, col2, col3) as
        2    (select 'cust1', 'y', 'y', 'n' from dual union
        3     select 'cust2', 'n', 'n', 'y' from dual union
        4     select 'cust3', 'y', 'n', 'y' from dual
        5    )
        6  select cname,
        7    sum(decode(col1, 'y', 1, 0) +
        8        decode(col2, 'y', 1, 0) +
        9        decode(col3, 'y', 1, 0)) sumc
       10  from test
       11  group by cname
       12  having sum(decode(col1, 'y', 1, 0) +
       13             decode(col2, 'y', 1, 0) +
       14             decode(col3, 'y', 1, 0)) >= 2
       15  order by cname;
      
      CNAME       SUMC
      ----- ----------
      cust1          2
      cust3          2
      
      SQL>
      

      【讨论】:

      • 不客气;不过,人们通常会支持他们认为有帮助的答案,所以 - 随意这样做。
      【解决方案4】:

      从你所展示的看来:

      • 您有一个包含三个布尔列的表。由于 Oracle DBMS 仍然不具有布尔数据类型,因此您使用 col1 CHAR(1) NOT NULL, CONSTRAINT chk_customers_bool_col1 CHECK (col1 in ('Y','N')) 等代替。 (遗憾的是,Oracle 强迫我们采用这种变通方法。)
      • 您正在显示一个客户表,其中每个客户一条记录和三个属性,在您的示例中称为 col1col2col3,但它们是现实生活中的真实属性,例如 quickfriendlyrich,并且您希望选择至少有两个属性为真的客户。

      一种简单的方法是连接三个字母,删除 N 并计算剩余的 Y。

      select
        Customer_Name, 
        length(replace(col1 || col2 ||| col3 ,'N',''))
      from customers
      where length(replace(col1 || col2 ||| col3 ,'N','')) >= 2;
      

      此查询仍然适用于三态布尔值(即允许 null),但如果列可以包含其他字符(例如“M”表示“可能”或“S”表示“有时”),则不能。在这种情况下,您必须使用 CASE 表达式或 Oracle 的 DECODE 来检查 Ys。


      许多人更喜欢数字 0 和 1 来模拟 Oracle 中的布尔值 false 和 true。与“N”和“Y”相比,一个优势是您可以快速将它们相加以计算有多少是正确的,这正是您的情况。 (在存在布尔数据类型的 MySQL 中,它们甚至允许用 0 替换 false 和 1 替换 true,因此 true + false + true = 2。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-11
        • 2023-02-24
        • 1970-01-01
        相关资源
        最近更新 更多