这是thread的延续 我有以下查询将值作为标题使用
SELECT *
FROM (SELECT prod_id,
start_date AS dt,
start_date,
hours
FROM prod_timings t) PIVOT (SUM (hours)
FOR start_date
IN (TO_DATE ('18-SEP-17', 'DD-MON-YY') AS wed,
TO_DATE ('19-SEP-17', 'DD-MON-YY') AS thu))
ORDER BY prod_id, dt
我可以使用以下查询在PIVOT的IN子句中使用日期动态吗?我们的想法是在IN子句中包含一个动态查询,以避免硬编码日期
SELECT *
FROM ( SELECT (TO_DATE (:end_date, 'DD-MM-YYYY') - LEVEL + 1) AS day
FROM DUAL
CONNECT BY LEVEL <=
( TO_DATE (:end_date, 'DD-MM-YYYY')
- TO_DATE (:start_date, 'DD-MM-YYYY')
+ 1))
绑定值
end_date - 19-Sep-17
start_date - 18-Sep-17
以上的输出是
19-Sep-17
18-Sep-17
预期输出
╔═════════╦════════════╦════════╦════════╦═══════════╗
║ PROD_ID ║ START_DATE ║ MON-18 ║ TUE-19 ║ TOT_HOURS ║
╠═════════╬════════════╬════════╬════════╬═══════════╣
║ PR220 ║ 19-Sep-17 ║ ║ 0 ║ 0 ║
║ PR2230 ║ 19-Sep-17 ║ ║ 2 ║ 2 ║
║ PR9702 ║ 19-Sep-17 ║ ║ 3 ║ 3 ║
║ PR9036 ║ 19-Sep-17 ║ ║ 0.6 ║ 0.6 ║
║ PR9036 ║ 18-Sep-17 ║ 3.4 ║ ║ 3.4 ║
║ PR9609 ║ 18-Sep-17 ║ 5 ║ ║ 5 ║
║ PR91034 ║ 18-Sep-17 ║ 4 ║ ║ 4 ║
║ PR7127 ║ 18-Sep-17 ║ 0 ║ ║ 0 ║
╚═════════╩════════════╩════════╩════════╩═══════════╝
表格结构和值
CREATE TABLE PROD_TIMINGS
(
PROD_ID VARCHAR2(12 BYTE),
START_DATE DATE,
TOT_HOURS NUMBER
);
SET DEFINE OFF;
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR220', TO_DATE('09/19/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 0);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR2230', TO_DATE('09/19/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 2);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR9702', TO_DATE('09/19/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 3);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR9036', TO_DATE('09/19/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 0.6);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR9036', TO_DATE('09/18/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 3.4);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR9609', TO_DATE('09/18/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 5);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR91034', TO_DATE('09/18/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 4);
Insert into PROD_TIMINGS
(PROD_ID, START_DATE, TOT_HOURS)
Values
('PR7127', TO_DATE('09/18/2017 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 0);
COMMIT;
答案 0 :(得分:1)
类似的东西:
VARIABLE cur REFCURSOR;
DECLARE
dates VARCHAR2(4000);
start_date DATE := DATE '2017-09-18';
end_date DATE := DATE '2017-09-19';
BEGIN
SELECT LISTAGG(
'DATE ''' || TO_CHAR( dt, 'YYYY-MM-DD' )
|| ''' AS "' || TO_CHAR( dt, 'FMDY-DD' ) || '"',
','
) WITHIN GROUP ( ORDER BY dt )
INTO dates
FROM (
SELECT start_date + LEVEL - 1 AS dt
FROM DUAL
CONNECT BY LEVEL <= end_date - start_date + 1
);
OPEN :cur FOR
'SELECT * FROM (
SELECT t.*,
MIN( start_date ) OVER ( PARTITION BY prod_id ) AS min_start_date,
SUM( tot_hours ) OVER ( PARTITION BY prod_id ) AS prod_tot_hours
FROM prod_timings t
WHERE start_date BETWEEN :1 AND :2
)
PIVOT (
SUM( tot_hours )
FOR start_date IN (' || dates || ')
)
ORDER BY prod_id'
USING start_date, end_date;
END;
/
PRINT cur;
答案 1 :(得分:0)
首先,当原始日期列也是预期输出的一部分时,按日期使用数据透视非常荒谬。这引入了新列,但行数保持不变。
其次,不可能使列名依赖于绑定值。列名在解析阶段中定义为,Oracle会针对不同的绑定重新使用相同的计划。
但是,如果您希望将start和end_date作为绑定传递并具有预定义的列标题,则可以使用
<强>更新强>
正常解决方案
SQL> select prod_id, dt,
2 sum(decode(dt, :start_date, tot_hours)) start_date_hours,
3 sum(decode(dt, :end_date, tot_hours)) end_date_hours,
4 sum(tot_hours) tot_hours
5 from (select prod_id, start_date as dt, start_date, tot_hours
6 from prod_timings t)
7 group by dt, prod_id
8 order by dt desc, prod_id;
PROD_ID DT START_DATE_HOURS END_DATE_HOURS TOT_HOURS
------------ --------- -------------------- -------------------- ----------
PR220 19-SEP-17 .0 0
PR2230 19-SEP-17 2.0 2
PR9036 19-SEP-17 .6 .6
PR9702 19-SEP-17 3.0 3
PR7127 18-SEP-17 .0 0
PR9036 18-SEP-17 3.4 3.4
PR91034 18-SEP-17 4.0 4
PR9609 18-SEP-17 5.0 5
8 rows selected.
奇怪的解决方案
SQL> with t as
2 (select *
3 from (select prod_id, start_date as dt, start_date, tot_hours
4 from prod_timings t)
5 pivot xml(sum(tot_hours) as s for start_date in
6 (select :start_date from dual union all select :end_date from dual)))
7 select prod_id, dt, start_date_hours, end_date_hours,
8 nvl(start_date_hours, end_date_hours) tot_hours
9 from t,
10 xmltable('/PivotSet' passing start_date_xml
11 columns
12 start_date_hours number
13 path '/PivotSet/item[1]/column[@name="S"]/text()',
14 end_date_hours number
15 path '/PivotSet/item[2]/column[@name="S"]/text()') x
16 order by dt desc, prod_id;
PROD_ID DT START_DATE_HOURS END_DATE_HOURS TOT_HOURS
------------ --------- -------------------- -------------------- ----------
PR220 19-SEP-17 .0 0
PR2230 19-SEP-17 2.0 2
PR9036 19-SEP-17 .6 .6
PR9702 19-SEP-17 3.0 3
PR7127 18-SEP-17 .0 0
PR9036 18-SEP-17 3.4 3.4
PR91034 18-SEP-17 4.0 4
PR9609 18-SEP-17 5.0 5
8 rows selected.
至于此任务的DSQL方法......这远远不是常识。