【问题标题】:Oracle APEX report with column count breakdown and filtering包含列计数细分和过滤的 Oracle APEX 报告
【发布时间】:2014-06-23 02:28:04
【问题描述】:

我正在编写以下 Oracle APEX v4.2.2 报告。它基本上需要:

  1. 所有部门的员工总数。
  2. 始终相同的 3 个部门(A、B 和 C)可能存在于不同的位置
  3. 每个地点可能有相同的 A、B 和 C 部门,但有些可能只有 A 或 A 和 B 或所有三个部门。
  4. 还需要员工部门分类计数(示例如下)
  5. 报告下方的整体复选框系统向用户显示报告中所有位置的不同部门列表,该列表将用作过滤器(示例如下所示)

示例报告可能如下所示:

Location          Dept A.     Dept. B     Dept. C      Total Employees
----------------- ----------- ----------- ------------ ---------------
Paris             5           10          3            18
Rome              10          20          5            35
London            40          -           30           70


Filter Departments: [X]Dept. A  [X]Dept. B  []Dept. C     [Apply Filter button]

所以使用上面的报告示例并假设通过三个表的 ids 存在数据库结构/连接:

location
department
employees

a) 我可以得到员工总数,但是对于上述每个位置部门来说,实现员工部门细分计数的最佳方法是什么,如报告中所示,即 A 部门 = 5,B 部门 = 10和C部门= 3?

b) 使用上面提到的过滤功能,如果我检查 Dept.A 和 Dept.B 然后按“应用过滤器按钮”,我需要根据检查的部门重新生成上面的报告并使用新值,所以新报告现在将如下所示:

Location          Dept A.     Dept. B     Total Employees
----------------- ----------- ----------- ---------------
Paris             5           10          15
Rome              10          20          30
London            40          -           40

【问题讨论】:

  • 这并不是真正的 Apex 挑战,它更像是 SQL 挑战。您需要做更多的工作 - 到目前为止,您的查询有什么想法?
  • 就复选框而言,这只是根据三个部门创建一个带有值列表的复选框项的问题;然后将显示条件放在报告列上以根据复选框项的值隐藏/显示它们。

标签: sql plsql oracle11g oracle-apex


【解决方案1】:

Is the following query possible with SQL Pivot?上查看我的回答

当您的数据被透视并且列是动态的时,您可以使用以下设置。你无法逃避一些plsql。

示例表和数据:

CREATE TABLE DEMO_LOCATIONS ( 
  ID   NUMBER(10) 
, NAME VARCHAR2(20)
, CONSTRAINT LOCATION_PK PRIMARY KEY (ID) 
);
CREATE TABLE DEMO_DEPARTMENTS ( 
  ID          NUMBER(10)
, LOCATION_ID NUMBER(10)
, NAME        VARCHAR2(20)
, CONSTRAINT DEPARTMENT_PK PRIMARY KEY (ID)
, CONSTRAINT DEPT_LOC_FK FOREIGN KEY (LOCATION_ID) REFERENCES DEMO_LOCATIONS (ID)
);
CREATE TABLE DEMO_EMPLOYEES (
  ID            NUMBER(10)
, DEPARTMENT_ID NUMBER(10)
, NAME          VARCHAR2(20)
, CONSTRAINT EMPLOYEES_PK PRIMARY KEY (ID) 
, CONSTRAINT EMPL_DEPT_FK FOREIGN KEY (DEPARTMENT_ID) REFERENCES DEMO_DEPARTMENTS (ID)
);

DECLARE
  l_emp_id NUMBER := 0;
BEGIN
  INSERT INTO demo_locations (id, name) VALUES (1, 'Paris');
  INSERT INTO demo_locations (id, name) VALUES (2, 'Rome');
  INSERT INTO demo_locations (id, name) VALUES (3, 'London');
  INSERT INTO
  INSERT INTO demo_departments(id, location_id, name) VALUES (1, 1, 'A');
  INSERT INTO demo_departments(id, location_id, name) VALUES (2, 1, 'B');
  INSERT INTO demo_departments(id, location_id, name) VALUES (3, 1, 'C');

  INSERT INTO demo_departments(id, location_id, name) VALUES (4, 2, 'A');
  INSERT INTO demo_departments(id, location_id, name) VALUES (5, 2, 'B');
  INSERT INTO demo_departments(id, location_id, name) VALUES (6, 2, 'C');

  INSERT INTO demo_departments(id, location_id, name) VALUES (7, 3, 'A');
  INSERT INTO demo_departments(id, location_id, name) VALUES (8, 3, 'B');
  INSERT INTO demo_departments(id, location_id, name) VALUES (9, 3, 'C');

  FOR I IN 1..9 LOOP
    FOR J IN 1..FLOOR(DBMS_RANDOM.VALUE(1,10)) LOOP
      l_emp_id := l_emp_id + 1;
      INSERT INTO demo_employees (id, department_id, name) VALUES (l_emp_id, i, 'employee #'||j);
    END LOOP;
  END LOOP;
END;
/
COMMIT;

WITH pivot_src AS (
  SELECT l.name location_name, d.name department_name, count(*) amount_employees
    FROM demo_locations l
    JOIN demo_departments d
      ON d.location_id = l.id
    JOIN demo_employees e
      ON e.department_id = d.id
   GROUP BY l.name, d.name
)
SELECT *
  FROM pivot_src
 pivot ( sum(amount_employees) as all_emps for department_name in ('A' as "Department A", 'B' as "Department B", 'C' as "Department C") );

顶点

报告来源:

DECLARE
  l_pivot_cols VARCHAR2(4000);
  l_pivot_qry VARCHAR2(4000);
BEGIN
  IF NVL(:PX_DEPTA, 'N') = 'Y' THEN
    l_pivot_cols := l_pivot_cols || '''A'' as "Department A",';
  END IF;
  IF NVL(:PX_DEPTB, 'N') = 'Y' THEN
    l_pivot_cols := l_pivot_cols || '''B'' as "Department B",';
  END IF;
  IF NVL(:PX_DEPTC, 'N') = 'Y' THEN
    l_pivot_cols := l_pivot_cols || '''C'' as "Department C",';
  END IF;

  l_pivot_cols := RTRIM(l_pivot_cols, ',');

  l_pivot_qry := 
   ' WITH pivot_src AS ( '
|| '   SELECT l.name location_name, d.name department_name, count(*) amount_employees '
|| '     FROM demo_locations l '
|| '     JOIN demo_departments d '
|| '       ON d.location_id = l.id '
|| '     JOIN demo_employees e '
|| '       ON e.department_id = d.id '
|| '    GROUP BY l.name, d.name '
|| ' ) '
|| ' SELECT * '
|| '   FROM pivot_src '
|| '  pivot ( sum(amount_employees) as all_emps for department_name in ('||l_pivot_cols||') ); ';

  RETURN l_pivot_qry;
END;

报告属性 > PLSQL 标题

DECLARE
  l_cols VARCHAR2(4000);
BEGIN
  l_cols := 'Location:';

  IF :PX_DEPTA = 'Y' THEN
    l_cols := l_cols || 'Department A:';
  END IF;
  IF :PX_DEPTB = 'Y' THEN
    l_cols := l_cols || 'Department B:';
  END IF;
  IF :PX_DEPTC = 'Y' THEN
    l_cols := l_cols || 'Department C:';
  END IF;

  RETURN RTRIM(l_cols, ':');
END;

制作3个复选框,默认Y,LOV:STATIC2:;Y。将项目添加到报告“要提交的页面项目”中。创建一个在项目更改时触发并刷新报告的动态操作。

【讨论】:

    【解决方案2】:

    对于 a 部分,看起来数据透视表是您的最佳选择。这是一篇不错的文章:http://www.oracle-base.com/articles/11g/pivot-and-unpivot-operators-11gr1.php

    对于 b 部分,这可能会变得很棘手。您需要确保 Dept C 员工没有出现在 Total Results 中,并且您需要隐藏 Dept C 列。

    拥有另一个复选框来指定包括所有部门可能是一个不错的用户界面功能,并且您可以通过动态操作在单击其他复选框时清除它。

    为确保 C 部门的员工不会出现在总数中,您可以在 WHERE 子句中添加以下内容:

    WHERE
     (
       (:PXX_DEPT_A_FILTER = 'Y' AND employee.department = 'A')
       OR 
       (:PXX_DEPT_B_FILTER = 'Y' AND employee.department = 'B')
       OR
       (:PXX_DEPT_C_FILTER = 'Y' AND employee.department = 'C')
       OR 
       :PXX_ALL_DEPTS_FILTER = 'Y'
     )
     AND
     ....
    

    要隐藏列,请使每列都以选中的适当过滤器为条件。

    您可以通过使用动态操作和部分页面刷新来消除过滤器按钮的使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-27
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多