Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle SQL Developer-不带聚合函数的透视表_Sql_Oracle_Pivot - Fatal编程技术网

Oracle SQL Developer-不带聚合函数的透视表

Oracle SQL Developer-不带聚合函数的透视表,sql,oracle,pivot,Sql,Oracle,Pivot,我有下表(根据实际情况简化) 基本上,我有多个项目(由ID列区分),在表中由4个属性列描述 它的工作方式是,对于每个AttributeName列,都有一个值,由AttributeValue列表示。每个属性都根据其类型分开(有string、int、bool等。为了简化问题,我只显示2) 当我说AttributeName时,它的意思是第2列或第4列。每个项目(ID列)都在多行中描述,其中每行只能包含一个属性(另一个属性为空)。因此,同一行中可能没有2个AttributeName。此外,并非所有对象都

我有下表(根据实际情况简化)

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

它的工作方式是,对于每个
AttributeName
列,都有一个值,由
AttributeValue
列表示。每个属性都根据其类型分开(有string、int、bool等。为了简化问题,我只显示2)

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

我的目标如下(解释如下):

如您所见,我希望每个属性,无论其类型(int、string等)如何,都是一列,并且结果位于每个项目的对应行中。此外,还有50多个不同的属性,它们可以随时间变化,因此动态变化的属性是最好的

我已经尝试了
PIVOT
函数,但是,首先,我认为它不起作用,因为没有聚合,其次,我不想要空列。我的查询也不起作用,因为有一个
“缺少表达式”

这是:

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')

这里有一个使用条件聚合的选项:

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 

这里有一个使用条件聚合的选项:

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 

使用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>

使用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>

我想到了这一点,但是属性有很多可能性(大约50个),它们可能会随着时间而改变,也可能不会。这就是为什么我要研究一个动态查询,使用
selectdistinct
来设置列。然而,我要补充一个事实,即在实际情况中,这个问题有许多属性。谢谢我想到了这一点,但是属性有很多可能性(大约50个),它们可能会随着时间而改变,也可能不会。这就是为什么我要研究一个动态查询,使用
selectdistinct
来设置列。然而,我要补充一个事实,即在实际情况中,这个问题有许多属性。谢谢这是可怕的实体属性值反模式。如果您正在使用的系统尚未投入生产,请停止并认真考虑重新设计它。您将面临大量过于复杂的查询、有限的引用完整性和糟糕的性能。如果您已经提交,请参阅此链接,了解使用Oracle数据盒带接口的动态
pivot
功能。我在生产中使用过它,效果很好。@Matthew McPeak:你忘了包括链接?我想看看:-)对不起。这里:可悲的是,我刚开始在这里工作,这个系统得到了深入的实施,所以没有办法回避它。谢谢你的链接,如果有用的话,我会提供更多的信息。谢谢这是可怕的实体属性值反模式。如果您正在使用的系统尚未投入生产,请停止并认真考虑重新设计它。您将面临大量过于复杂的查询、有限的引用完整性和糟糕的性能。如果您已经提交,请参阅此链接,了解使用Oracle数据盒带接口的动态
pivot
功能。我在生产中使用过它,效果很好。@Matthew McPeak:你忘了包括链接?我想看看:-)对不起。这里:可悲的是,我刚开始在这里工作,这个系统得到了深入的实施,所以没有办法回避它。谢谢你的链接,如果有用的话,我会提供更多的信息。谢谢它编译时出现以下错误:1-
7/11 PL/SQL:SQL语句被忽略
2-
8/46 PL/SQL:ORA-01790:表达式必须与相应表达式具有相同的数据类型
3-
16/5 PL/SQL:Statement被忽略
4-
17/30 PLS-00364:循环索引变量“R”的使用是错误的无效
好吧,我通过将INT_ATTRIBUTEVALUE转换为varchar2(50)来修复它。那应该行,谢谢!它编译时出现以下错误:1-
7/11 PL/SQL:SQL语句被忽略
2-
8/46 PL/SQL:ORA-01790:表达式必须与相应表达式具有相同的数据类型
3-
16/5 PL/SQL:Statement被忽略
4-
17/30 PLS-00364:循环索引变量“R”的使用是错误的无效
好吧,我通过将INT_ATTRIBUTEVALUE转换为varchar2(50)来修复它。那应该行,谢谢!