创建动态数据透视表 - 基于2个常用字段将多行输入字段

时间:2015-11-26 19:56:31

标签: sql oracle oracle11g

如何将PONT_LOC字段转换为每个值的单独字段,从而为每个SECTION&创建一行。 SURVEY_DATE组合,行数总是非常基于SECTION& SURVEY_DATE,有人可以帮忙吗? Oracle11g的

SELECT * FROM (SELECT STATE_CODE||SHRP_ID AS SECTION, SURVEY_DATE, POINT_LOC
FROM (SELECT * FROM MON_DIS_JPCC_FAULT ORDER BY STATE_CODE, SHRP_ID, SURVEY_DATE, POINT_LOC)
WHERE STATE_CODE=55
AND SHRP_ID LIKE '0213'
AND CRACK_OR_JOINT='J'
AND SURVEY_DATE='04/27/1998');

+---------+-------------+-----------+
| SECTION | SURVEY_DATE | POINT_LOC |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 3.2       |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 7.9       |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 12.5      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 17.1      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 21.7      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 26.2      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 30.7      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 35.2      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 39.8      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 44.4      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 48.9      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 53.5      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 58        |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 62.8      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 67.1      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 71.7      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 76.5      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 81.2      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 85.6      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 90.2      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 94.7      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 99.4      |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 103.9     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 108.3     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 114       |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 117.7     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 122.1     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 126.7     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 131.3     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 136       |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 140.5     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 144.9     |
+---------+-------------+-----------+
| 550213  | 04/27/1998  | 149.4     |
+---------+-------------+-----------+

以下是一些示例数据:

CREATE TABLE MON_DIS_JPCC_FAULT
(SECTION VARCHAR(255),
SURVEY_DATE VARCHAR(255),
POINT_LOC DECIMAL(3,1));

INSERT INTO MON_DIS_JPCC_FAULT
VALUES ('550213', '04/27/1998', 3.2);

INSERT INTO MON_DIS_JPCC_FAULT
VALUES ('550213', '04/27/1998', 7.9);

INSERT INTO MON_DIS_JPCC_FAULT
VALUES ('550213', '04/27/1998', 12.5);

INSERT INTO MON_DIS_JPCC_FAULT
VALUES ('550213', '04/27/1998', 17.1);

INSERT INTO MON_DIS_JPCC_FAULT
VALUES ('550213', '04/27/1998', 21.7);

我不知道我的解释是否正确...这里是我正在寻找的输出样本:

+---------+-------------+-------------+-------------+-------------+-------------+-------------+
| SECTION | SURVEY_DATE | POINT_LOC_1 | POINT_LOC_2 | POINT_LOC_3 | POINT_LOC_4 | POINT_LOC_5 |...6, 7, 8, etc...
+---------+-------------+-------------+-------------+-------------+-------------+-------------+
| 550213  | 04/27/1998  | 3.2         | 7.9         | 12.5        | 17.1        | 21.7        |
+---------+-------------+-------------+-------------+-------------+-------------+-------------+

此外,POINT_LOC的数量总是不同。

我希望这是有道理的,非常感谢任何帮助!

好的,这是我到目前为止:

SELECT * FROM (
SELECT STATE_CODE||SHRP_ID AS SECTION, SURVEY_DATE, ROW_NUMBER() OVER (PARTITION BY STATE_CODE, SHRP_ID, SURVEY_DATE ORDER BY STATE_CODE, SHRP_ID, SURVEY_DATE, POINT_LOC) AS "JOINT_NO", POINT_LOC
FROM MON_DIS_JPCC_FAULT
WHERE STATE_CODE=55
AND SHRP_ID IN ('0215','0216')
AND CRACK_OR_JOINT='J')

PIVOT (MAX("POINT_LOC") FOR JOINT_NO IN (1,2,3,4,5,34,35,36))

ORDER BY "SECTION", SURVEY_DATE

以下是一个示例结果:

+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| SECTION | SURVEY_DATE | 1   | 2   | 3    | 4    | 5    | 34    | 35    | 36 |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550215  | 04/28/1998  | 3.1 | 7.9 | 12.5 | 17.1 | 21.7 | -     | -     | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550215  | 06/08/2000  | 3.1 | 7.9 | 12.5 | 17.1 | 21.7 | -     | -     | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550215  | 04/22/2002  | 3.1 | 7.9 | 12.5 | 17.1 | 21.7 | -     | -     | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550215  | 08/15/2005  | 3.1 | 7.9 | 12.5 | 17.1 | 21.7 | -     | -     | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550215  | 05/12/2010  | 3.1 | 7.9 | 12.5 | 17.1 | 21.7 | -     | -     | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550215  | 07/31/2012  | 3.1 | 7.9 | 12.5 | 17.1 | 21.7 | -     | -     | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550216  | 04/24/1998  | 3   | 7.5 | 12   | 16.6 | 21.1 | 148   | 152.4 | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550216  | 06/06/2000  | 3   | 7.5 | 12   | 16.6 | 21.1 | 148   | 152.4 | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550216  | 04/16/2002  | 3   | 7.5 | 12   | 16.6 | 21.1 | 148   | 152.4 | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550216  | 08/12/2005  | 3   | 7.5 | 12   | 16.6 | 21.1 | 148   | 152.4 | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550216  | 05/05/2010  | 3   | 7.5 | 12   | 16.6 | 21.1 | 152.3 | 152.4 | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+
| 550216  | 07/30/2012  | 3   | 7.5 | 12   | 16.6 | 21.1 | 148   | 152.4 | -  |
+---------+-------------+-----+-----+------+------+------+-------+-------+----+

问题是POINT_LOC的数量会因SECTION而异,所以我需要SQL的“IN(1,2,3,4,5,34,35,36)”部分来确定行数,只包括那些。我试图添加一个子查询,但我不断收到“缺少表达式”错误,请帮助: - (

1 个答案:

答案 0 :(得分:0)

如果我的理解是正确的,您希望每个POINT_LOC SECTION & SURVEY_DATE都在一行中。

您可以在此方案中使用命令LISTAGG。

SELECT SECTION
       , SURVEY_DATE
       , LISTAGG(POINT_LOC) WITHIN GROUP (ORDER BY SECTION) POINT_LOC
  FROM ...
GROUP BY SECTION, SURVEY_DATE;

希望这会有所帮助。

修改

方法:字符串cocatenation

CREATE OR REPLACE PROCEDURE PVT (
    CUR_PIVOT   OUT SYS_REFCURSOR
)
AS
    V_SQL       VARCHAR2(4000);
    V_ROW       VARCHAR2(4000);

BEGIN    
    SELECT LISTAGG(RN, ',') WITHIN GROUP (ORDER BY RN)
      INTO V_ROW
      FROM (SELECT DISTINCT ROW_NUMBER() OVER (PARTITION BY SECTION, SURVEY_DATE ORDER BY SECTION, SURVEY_DATE, POINT_LOC) RN
              FROM MON_DIS_JPCC_FAULT);

    V_SQL := 'SELECT * FROM (' ||
             'SELECT SECTION, SURVEY_DATE, ROW_NUMBER() OVER (PARTITION BY SECTION, SURVEY_DATE ORDER BY SECTION, SURVEY_DATE, POINT_LOC) AS JOINT_NO, POINT_LOC FROM MON_DIS_JPCC_FAULT' ||
             ') PIVOT (' ||
             'MAX(POINT_LOC)' ||
             'FOR JOINT_NO IN (' || V_ROW || '))';

    DBMS_OUTPUT.PUT_LINE(V_SQL);

    OPEN CUR_PIVOT FOR V_SQL;
END PVT;

您可以通过以下方式致电然后获取结果:

VARIABLE DT REFCURSOR;
EXEC PVT(:X);
PRINT X;

但是,字符串长度存在限制。