【问题标题】:Oracle XE, count and display different combinations of rows based on one columnOracle XE,根据一列计算和显示不同的行组合
【发布时间】:2016-04-08 06:59:48
【问题描述】:

在复杂查询方面需要帮助。这是我表的摘录:

USERID    SERVICE
1         A
1         B
2         A
3         A
3         B
4         A
4         C
5         A
6         A
7         A
7         B

好的,我希望查询返回并显示我的表中存在的所有可能的组合,并根据 SERVICE 列显示它们各自的计数。例如,第一个用户有 A 和 B 服务,这是一次发生的组合。下一个用户只有服务 A,这是又一次发生的组合。第三个用户有服务 A 和 B,这已经发生过一次,这个组合的计数现在是 2,等等。所以我基于这个特定输入的输出将是这样的表:

A  AB  AC  ABC  B  BC
3  3   1   0    0  0

所以再澄清一点,如果有 3 个服务,那么就有 3 个!可能的组合; 3x2x1=6,它们是 A、B、C、AB、AC、BC 和 ABC。我的表应该包含分配了这些服务组合的用户数。

我尝试使用此查询构建矩阵,然后使用 CUBE 函数获取所有计数:

select service_A, service_B, service_C from 
  (select USERID,
  max(case when SERVICE =A then 1 else null end) service_A,
  max(case when SERVICE =B then 1 else null end) service_B,
  max(case when SERVICE =C then 1 else null end) service_C
  from SOME_TABLE) 
group by CUBE(service_A, service_B,service_C);

但我没有得到所有组合的计数。我只需要发生的组合,所以计数 0 不是必需的,但可以显示它们。谢谢。

【问题讨论】:

  • 你有一组可能的组合吗?也就是说,您是否事先知道您的查询将返回多少列?如果没有,你不能用一个简单的查询来做到这一点,但你需要一些动态的东西(然后很难处理一个列数未知的结果集)
  • 我知道哪些服务可用,例如一个人可以拥有 10 种服务。所以有可能进行计算,发现有10个!不同服务组合的数量,这是一个巨大的数字。所以这将是最大列数。但他们中的大多数都会有计数 0,问题是我不知道哪些所以我需要计算所有。

标签: sql oracle combinations permutation


【解决方案1】:

不要将其输出为动态列(不使用 PL/SQL 和动态 SQL 很难做到),而是将其输出为行(如果您有前端,那么它通常可以更轻松地将行转换为列比 oracle 可以):

Oracle 设置

CREATE TABLE some_table ( USERID, SERVICE ) AS
SELECT 1, 'A' FROM DUAL UNION ALL
SELECT 1, 'B' FROM DUAL UNION ALL
SELECT 2, 'A' FROM DUAL UNION ALL
SELECT 3, 'A' FROM DUAL UNION ALL
SELECT 3, 'B' FROM DUAL UNION ALL
SELECT 4, 'A' FROM DUAL UNION ALL
SELECT 4, 'C' FROM DUAL UNION ALL
SELECT 5, 'A' FROM DUAL UNION ALL
SELECT 6, 'A' FROM DUAL UNION ALL
SELECT 7, 'A' FROM DUAL UNION ALL
SELECT 7, 'B' FROM DUAL;

查询

SELECT service,
       COUNT( userid ) AS num_users
FROM   (
  SELECT userid,
         LISTAGG( service ) WITHIN GROUP ( ORDER BY service ) AS service
  FROM   some_table
  GROUP BY userid
)
GROUP BY service;

输出

SERVICE  NUM_USERS
------- ----------
AC               1 
A                3 
AB               3 

用于动态列的 PL/SQL

VARIABLE cur REFCURSOR;

DECLARE
  TYPE string_table IS TABLE OF VARCHAR2(4000);
  TYPE int_table IS TABLE OF INT;
  t_services string_table;
  t_counts   int_table;
  p_sql      CLOB;
BEGIN
  SELECT service,
         COUNT( userid ) AS num_users
  BULK COLLECT INTO t_services, t_counts
  FROM   (
    SELECT userid,
           CAST( LISTAGG( service ) WITHIN GROUP ( ORDER BY service ) AS VARCHAR2(2) ) AS service
    FROM   some_table
    GROUP BY userid
  )
  GROUP BY service;

  p_sql := EMPTY_CLOB() || 'SELECT ';
  p_sql := p_sql || t_counts(1) || ' AS "' || t_services(1) || '"';
  FOR i IN 2 .. t_services.COUNT LOOP
    p_sql := p_sql || ', ' || t_counts(i) || ' AS "' || t_services(i) || '"';
  END LOOP;
  p_sql := p_sql || ' FROM DUAL';

  OPEN :cur FOR p_sql;
END;
/

PRINT cur;

输出

AC  A   AB
--- --- ---
1   3   3  

【讨论】:

  • 哇,谢谢你快速准确的回复,这正是我想要的!!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
相关资源
最近更新 更多