【发布时间】:2018-11-27 17:41:10
【问题描述】:
我有下表(从现实中简化)。
| 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 |
基本上,我有多个项目(由 ID 列区分)在表中由 4 个属性列描述。
它的工作方式是,对于每个AttributeName 列,都有一个值,由AttributeValue 列表示。每个属性根据其类型进行分隔(有string、int、bool等。为了简化问题,我只显示2个)。
当我说AttributeName 时,它表示第 2 列或第 4 列。每个项目(ID 列)用多行描述,其中每一行可能只包含 一个 属性(另一个将为空)。因此,同一行中可能没有 2 个AttributeName。此外,并非所有对象都具有所有现有属性(ID 3 具有所有属性,而 1 和 2 没有);但是,在任一类型的 AttributeName 中执行 DISTINCT SELECT 将选择每个 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')
【问题讨论】:
-
这是可怕的实体-属性-值反模式。如果您正在开发的这个系统尚未投入生产,请停止并认真考虑重新设计它。您正在处理大量过于复杂的查询、有限的引用完整性和糟糕的性能。如果您已经提交,请参阅此链接以获取使用 Oracle 数据盒接口的动态
pivot函数。我已经在生产环境中使用它并且效果很好。 -
@Matthew McPeak :您忘记包含链接了?我希望看到它:-)
-
很遗憾,我刚开始在这里工作,这个系统已经深入实施,所以没有办法躲避它。感谢您的链接,如果它有效,我将提供更多信息。谢谢!