问题描述
我有下面的测试用例(见下面) ,它工作的很好。我希望所有的信息都显示为原样。问题是,我只想按access_date、雇员ID分组。当我删除第一个分组集时,我得到错误“无效分组依据”。有什么办法可以绕过这个问题吗?
ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS'; CREATE OR REPLACE TYPE nt_date IS TABLE OF DATE; / CREATE OR REPLACE FUNCTION generate_dates_pipelined( p_from IN DATE, p_to IN DATE ) RETURN nt_date PIPELINED DETERMINISTIC IS v_start DATE := TRUNC(LEAST(p_from, p_to)); v_end DATE := TRUNC(GREATEST(p_from, p_to)); BEGIN LOOP PIPE ROW (v_start); EXIT WHEN v_start >= v_end; v_start := v_start + INTERVAL '1' DAY; END LOOP; RETURN; END generate_dates_pipelined; / create table employees( employee_id NUMBER(6), first_name VARCHAR2(20), last_name VARCHAR2(20), card_num VARCHAR2(10), work_days VARCHAR2(7) ); ALTER TABLE employees ADD ( CONSTRAINT employees_pk PRIMARY KEY (employee_id) ); INSERT INTO employees ( EMPLOYEE_ID, first_name, last_name, card_num, work_days ) WITH names AS ( SELECT 1, 'Jane', 'Doe', 'F123456', 'NYYYYYN' FROM dual UNION ALL SELECT 2, 'Madison', 'Smith', 'R33432','NYYYYYN' FROM dual UNION ALL SELECT 3, 'Justin', 'Case', 'C765341','NYYYYYN' FROM dual UNION ALL SELECT 4, 'Mike', 'Jones', 'D564311','NYYYYYN' FROM dual ) SELECT * FROM names; CREATE TABLE locations AS SELECT level AS location_id, 'Door ' || level AS location_name, CASE round(dbms_random.value(1,3)) WHEN 1 THEN 'T' WHEN 2 THEN 'T' WHEN 3 THEN 'T' END AS location_type FROM dual CONNECT BY level <= 3; ALTER TABLE locations ADD ( CONSTRAINT locations_pk PRIMARY KEY (location_id)); create table access_history( seq_num integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL, employee_id NUMBER(6), card_num varchar2(10), location_id number(4), access_date date, processed NUMBER(1) default 0 ); create or replace procedure create_access_history(p_start_date date, p_end_date date) IS BEGIN INSERT into access_history ( employee_id, card_num, location_id, access_date ) WITH cntr AS ( SELECT LEVEL - 1 AS n FROM dual CONNECT BY LEVEL <= 15 -- Max number of rows per employee per date ) , got_location_num AS ( SELECT location_id , ROW_NUMBER () OVER (ORDER BY location_id) AS location_num , COUNT (*) OVER () AS max_location_num FROM locations ) , employee_days AS ( SELECT e.employee_id, e.card_num , d.column_value AS access_date , dbms_random.value (0, 15) AS rn -- 0 to max number of rows per employee per date FROM employees e CROSS JOIN TABLE (generate_dates_pipelined (p_start_date, p_end_date)) d ) , employee_n_days AS ( SELECT ed.employee_id, ed.card_num, ed.access_date , dbms_random.value (0, 1) AS lrn FROM employee_days ed JOIN cntr c ON c.n <= ed.rn ) SELECT n.employee_id, n.card_num, l.location_id, n.access_date + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(0,86399)), 'SECOND') FROM employee_n_days n JOIN got_location_num l ON l.location_num = CEIL (n.lrn * l.max_location_num); END; / EXEC create_access_history (SYSDATE, SYSDATE+3); select TRUNC(a. access_date) access_date, e.employee_id, e.first_name, e.last_name, e.card_num, l.location_id, l.location_name, count(*) cnt FROM employees e JOIN access_history a ON a.employee_id = e.employee_id JOIN locations l ON l.location_id = a.location_id GROUP BY GROUPING SETS ( (TRUNC(a.access_date), e.employee_id, e.first_name, e.last_name, e.card_num, l.location_id, l.location_name), (TRUNC(a.access_date), e.employee_id), (trunc(a.access_date)), () ) ORDER BY trunc(a. access_date),e.employee_id,l.location_id;复制
专家解答
你是说你做这个的时候会得到ORA-979 ?
如果是这样,问题是选择列表(和排序依据)中的所有非聚合列也必须在您的分组依据中。
因此,您需要从选择和排序依据中删除这些列,或者将它们包括在您的组中,例如:
如果要在输出中包括这些列,但“不关心”它们有哪些值,则可以从21c中使用any_value函数:
select TRUNC(a. access_date) access_date, e.employee_id, e.first_name, e.last_name, e.card_num, l.location_id, l.location_name, count(*) cnt FROM employees e JOIN access_history a ON a.employee_id = e.employee_id JOIN locations l ON l.location_id = a.location_id GROUP BY GROUPING SETS ( (TRUNC(a.access_date), e.employee_id), (trunc(a.access_date)), () ) ORDER BY trunc(a. access_date),e.employee_id,l.location_id; ORA-00979: not a GROUP BY expression复制
如果是这样,问题是选择列表(和排序依据)中的所有非聚合列也必须在您的分组依据中。
因此,您需要从选择和排序依据中删除这些列,或者将它们包括在您的组中,例如:
select TRUNC(a. access_date) access_date, e.employee_id, count(*) cnt FROM employees e JOIN access_history a ON a.employee_id = e.employee_id JOIN locations l ON l.location_id = a.location_id GROUP BY GROUPING SETS ( (TRUNC(a.access_date), e.employee_id), (trunc(a.access_date)), () ) ORDER BY trunc(a. access_date),e.employee_id; ACCESS_DATE EMPLOYEE_ID CNT 08032021 00:00:00 1 4 08032021 00:00:00 2 6 08032021 00:00:00 3 8 08032021 00:00:00 4 9 08032021 00:00:0027 08042021 00:00:00 1 5 08042021 00:00:00 2 9 ... 复制
如果要在输出中包括这些列,但“不关心”它们有哪些值,则可以从21c中使用any_value函数:
select TRUNC(a. access_date) access_date, e.employee_id, any_value ( e.first_name ), any_value ( e.last_name ), any_value ( e.card_num ), any_value ( l.location_id ), any_value ( l.location_name ), count(*) cnt FROM employees e JOIN access_history a ON a.employee_id = e.employee_id JOIN locations l ON l.location_id = a.location_id GROUP BY GROUPING SETS ( (TRUNC(a.access_date), e.employee_id), (trunc(a.access_date)), () ) ORDER BY trunc(a. access_date),e.employee_id; ACCESS_DATE EMPLOYEE_ID ANY_VALUE(E.FIRST_NAME) ANY_VALUE(E.LAST_NAME) ANY_VALUE(E.CARD_NUM) ANY_VALUE(L.LOCATION_ID) ANY_VALUE(L.LOCATION_NAME) CNT 08032021 00:00:00 1 Jane Doe F123456 1 Door 1 3 08032021 00:00:00 2 Madison Smith R33432 1 Door 1 4 08032021 00:00:00 3 Justin Case C765341 1 Door 1 5 08032021 00:00:00 4 Mike Jones D564311 1 Door 1 11 08032021 00:00:00Madison Smith R33432 1 Door 1 23 08042021 00:00:00 1 Jane Doe F123456 1 Door 1 9 08042021 00:00:00 2 Madison Smith R33432 1 Door 1 7 ... 复制
文章转载自askTom,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
Oracle DataGuard高可用性解决方案详解
孙莹
552次阅读
2025-03-26 23:27:33
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
515次阅读
2025-04-15 17:24:06
XTTS跨版本迁移升级方案(11g to 19c RAC for Linux)
zwtian
419次阅读
2025-04-08 09:12:48
墨天轮个人数说知识点合集
JiekeXu
417次阅读
2025-04-01 15:56:03
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
415次阅读
2025-04-18 14:18:38
Oracle SQL 执行计划分析与优化指南
Digital Observer
412次阅读
2025-04-01 11:08:44
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
376次阅读
2025-04-20 10:07:02
Oracle 19c RAC更换IP实战,运维必看!
szrsu
357次阅读
2025-04-08 23:57:08
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
335次阅读
2025-04-17 17:02:24
oracle定时任务常用攻略
virvle
324次阅读
2025-03-25 16:05:19