Oracle SQL Developer - 没有聚合函数的Pivot表

时间:2018-06-18 20:18:04

标签: sql oracle pivot

我有下表(从现实中简化)。

 | ID | String_AttributeName | String_AttributeValue | Int_AttributeName | Int_AttributeValue |
 |----|----------------------|-----------------------|-------------------|--------------------|
 | 1  | Name                 | Object1               |                   |                    |
 | 1  | (null)               | (null)                | Age               | 5                  |
 | 2  | Name                 | Object2               |                   |                    |
 | 2  | Location             | Canada                | (null)            | (null)             |
 | 2  | (null)               | (null)                | Quantity          | 2                  |
 | 3  | Name                 | Object3               |                   |                    |
 | 3  | (null)               | (null)                | Age               | 3                  |
 | 3  | (null)               | (null)                | Quantity          | 4                  |

基本上,我有4个属性列在表格中描述的多个项目(由ID列区分)。

它的工作方式是,对于每个AttributeName列,都有一个值,由AttributeValue列表示。每个属性根据其类型分隔(有字符串,整数,布尔等。我只会显示2以简化问题)。

当我说AttributeName时,它表示列#2或#4。每个项目(ID列)都以多行描述,其中每行只能包含一个属性(另一行将为null)。因此,同一行中可能不会有2 AttributeName。此外,并非所有对象都具有所有现有属性(ID 3具有所有属性,而1和2不具有所有属性);但是,在任一类型的DISTINCT SELECT中执行AttributeName都会选择每AttributeName个可能性

我的目标如下(以下说明):

+----+---------+--------+----------+
| ID | Name    | Age    | Quantity |
+----+---------+--------+----------+
| 1  | Object1 | 5      | (null)   |
+----+---------+--------+----------+
| 2  | Object2 | (null) | 2        |
+----+---------+--------+----------+
| 3  | Object3 | 3      | 4        |
+----+---------+--------+----------+

正如您所看到的,我希望每个属性,无论其类型(int,string等)是一个列,结果都在每个项目的相应行中。此外,有超过50种不同的属性,它们可以随时间变化,因此动态变化的东西将是最好的。

我已经尝试了PIVOT功能,但是,首先,我不认为它会起作用,因为没有聚合,其次,我不想要空列。由于存在"missing expression"

,我的查询也无法正常运行

这是:

SELECT  *
FROM   
(
    SELECT  ID
            ,STRING_ATTRIBUTENAME
    FROM    PIVOTTABLE
)
PIVOT
(
    COUNT(STRING_ATTRIBUTENAME)
    FOR STRING_ATTRIBUTENAME IN (SELECT DISTINCT PIVOTTABLE.STRING_ATTRIBUTENAME     FROM PIVOTTABLE)
)
ORDER BY PARTNUMBER; 

我上次做SQL开发已经有一段时间了(我曾经做过SQL Server),所以它有点生疏了。我只是不知道要尝试的其他方法,我目前正在寻找是否有办法通过选择AttributeName列来执行一些动态SQL。

任何线索也会有所帮助。谢谢!

------------ 这是重新创建起始表:

CREATE TABLE PIVOTTABLE 
(
  ID NUMBER NOT NULL 
, STRING_ATTRIBUTENAME VARCHAR2(50) 
, STRING_ATTRIBUTEVALUE VARCHAR2(50) 
, INT_ATTRIBUTENAME VARCHAR2(50) 
, INT_ATTRIBUTEVALUE NUMBER 
);

INSERT INTO TestTable VALUES('1','Name','Object1','','')
INSERT INTO TestTable VALUES('1','','','Age','5')
INSERT INTO TestTable VALUES('2','Name','Object2','','')
INSERT INTO TestTable VALUES('2','','','Quantity','2')
INSERT INTO TestTable VALUES('3','Name','Object3','','')
INSERT INTO TestTable VALUES('3','','','Age','3')
INSERT INTO TestTable VALUES('3','','','Quantity','4')

2 个答案:

答案 0 :(得分:1)

以下是使用conditional aggregation的一个选项:

select id, 
       max(case when string_attributename = 'Name' then string_attributevalue end) as Name,
       max(case when int_attributename = 'Age' then int_attributevalue end) as Age,
       max(case when int_attributename = 'Quantity' then int_attributevalue end) as Quantity
from pivottable
group by id 

答案 1 :(得分:1)

使用PL / SQL和动态查询 -

CREATE OR REPLACE PROCEDURE TMP_C(P OUT SYS_REFCURSOR)AS
    QRY VARCHAR2(1024) := 'SELECT ID ';
    C SYS_REFCURSOR;

BEGIN

FOR R IN (SELECT DISTINCT STRING_ATTRIBUTENAME FROM (
            SELECT ID, STRING_ATTRIBUTENAME, STRING_ATTRIBUTEVALUE
            FROM TABLE1
            WHERE STRING_ATTRIBUTENAME IS NOT NULL
            UNION
            SELECT ID, INT_ATTRIBUTENAME, INT_ATTRIBUTEVALUE
            FROM TABLE1
            WHERE INT_ATTRIBUTENAME IS NOT NULL))
LOOP
    QRY := QRY ||REPLACE(', MAX(DECODE(STRING_ATTRIBUTENAME,''$X'',STRING_ATTRIBUTEVALUE)) AS $X '
                       ,'$X',R.STRING_ATTRIBUTENAME );

END LOOP;
QRY := QRY ||' FROM ((
SELECT ID, STRING_ATTRIBUTENAME, STRING_ATTRIBUTEVALUE
FROM TABLE1
WHERE STRING_ATTRIBUTENAME IS NOT NULL
UNION
SELECT ID, INT_ATTRIBUTENAME, INT_ATTRIBUTEVALUE
FROM TABLE1
WHERE INT_ATTRIBUTENAME IS NOT NULL)) GROUP BY ID ';

OPEN P FOR QRY;

END;
/

执行 -

SQL> variable x refcursor
SQL> exec tmp_c(:x);

PL/SQL procedure successfully completed.

SQL> print x

        ID QUANTIT LOCATIO AGE     NAME
---------- ------- ------- ------- -------
         1                 5       Object1
         2 2       Canada          Object2
         3 4               3       Object3

SQL>
相关问题