我有下表(从现实中简化)。
| 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')
答案 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>