动态pivot plsql

时间:2016-02-25 01:43:11

标签: sql plsql

您好我有一个非常大的数据集,我想动态创建列并将值放在行中。

以下是数据集

Colorid color
1       Red
1       Blue
1       Yellow
2       Grey
2       Red

这是我想要回归的。我想我需要一个动态的支点,但不确定是的,不是没有

Colorid red blue yellow grey 
1       Yes yes  yes
2       Yes no   No     Yes

由于

2 个答案:

答案 0 :(得分:0)

如果需要在pl sql函数或过程中使用结果,可以执行以下操作。

DECLARE
 -- Local variables here
 sql_          VARCHAR2(32000);
 l_colCnt      NUMBER;
 l_descTbl     dbms_sql.desc_tab;
 fdbk          NUMBER;
 cur           NUMBER;
 pVarcharValue VARCHAR2(200);
BEGIN
 -- Test statements here
 sql_ := 'select to_char(Colorid) Colorid ';
 FOR c IN (SELECT DISTINCT color FROM COLOR_TABLE ORDER BY color) LOOP
        sql_ := sql_ || ', nvl((select ''yes'' from COLOR_TABLE where Colorid=a.Colorid and color=''' || c.color || '''),''no'') ' || c.color || ' ';
 END LOOP;
 sql_ := sql_ || ' from (select distinct Colorid from COLOR_TABLE) a';

 cur := DBMS_SQL.open_cursor;
 DBMS_SQL.PARSE(cur, sql_, DBMS_SQL.V7);
 dbms_sql.describe_columns(c => cur, col_cnt => l_colCnt, desc_t => l_descTbl);

 FOR i IN 1 .. l_colCnt LOOP
        dbms_output.put(l_descTbl(i).col_name||' '); -- Here name of column
        dbms_sql.define_column(cur, i, pVarcharValue, 200);
 END LOOP;
 dbms_output.put_line(NULL);
 fdbk := DBMS_SQL.execute(cur);
 LOOP
        fdbk := DBMS_SQL.fetch_rows(cur);

        EXIT WHEN fdbk = 0;
        FOR i IN 1 .. l_colCnt LOOP
             dbms_sql.column_value(cur, i, pVarcharValue);
             dbms_output.put(pVarcharValue || ' '); -- Here stored value of current row and column. One cell.
        END LOOP;
        dbms_output.put_line(NULL);
 END LOOP;
END;

如果您需要sys_refcursor,您可以这样做:

DECLARE
 -- Local variables here
 sql_          VARCHAR2(32000);
 curs          SYS_REFCURSOR;
BEGIN
 -- Test statements here
 sql_ := 'select to_char(Colorid) Colorid ';
 FOR c IN (SELECT DISTINCT color FROM COLOR_TABLE ORDER BY color) LOOP
        sql_ := sql_ || ', nvl((select ''yes'' from COLOR_TABLE where Colorid=a.Colorid and color=''' || c.color || '''),''no'') ' || c.color || ' ';
 END LOOP;
 sql_ := sql_ || ' from (select distinct Colorid from COLOR_TABLE) a';
 OPEN curs FOR sql_; -- here init sys_refcursor
END;

答案 1 :(得分:-1)

您好我们可以使用Pivot和IIF条件实现这一目标

普通查询

DECLARE @Table1 TABLE 
    (Colorid int, color varchar(6))
;

INSERT INTO @Table1
    (Colorid, color)
VALUES
    (1, 'Red'),
    (1, 'Blue'),
    (1, 'Yellow'),
    (2, 'Grey'),
    (2, 'Red')
;

Select Colorid,IIF([Red] IS NOT NULL,'YES','NO')[Red],IIF([Blue] IS NOT NULL,'YES','NO')[Blue],IIF([Yellow] IS NOT NULL,'YES','NO')[Yellow],IIF([Grey] IS NOT NULL,'YES','NO')[Grey] from (
select Colorid, color,ROW_NUMBER()OVER(PARTITION BY color ORDER BY color)RN from @Table1
GROUP BY Colorid, color)T
PIVOT (MAX(RN) FOR color IN ([Blue],[Red],[Yellow],[Grey]))P

动态查询

if object_id('tempdb..#t') is not null
    drop table #t


CREATE  TABLE #t
    (Colorid int, color varchar(6))
;

INSERT INTO #t
    (Colorid, color)
VALUES
    (1, 'Red'),
    (1, 'Blue'),
    (1, 'Yellow'),
    (2, 'Grey'),
    (2, 'Red')
;


DECLARE @statement NVARCHAR(max)
,@columns NVARCHAR(max)

SELECT @columns = ISNULL(@columns + ', ', '') + N'[' + tbl.color + ']'
FROM (
   SELECT DISTINCT color
   FROM #t
   ) AS tbl

SELECT @statement = ' Select Colorid,IIF([Red] IS NOT NULL,''YES'',''NO'')[Red],
IIF([Blue] IS NOT NULL,''YES'',''NO'')[Blue],
IIF([Yellow] IS NOT NULL,''YES'',''NO'')[Yellow],
IIF([Grey] IS NOT NULL,''YES'',''NO'')[Grey] from (
select Colorid, color,ROW_NUMBER()OVER(PARTITION BY color ORDER BY color)RN from #t
GROUP BY Colorid, color)T
PIVOT (MAX(RN) FOR color IN (' + @columns + ')) as pvt'

EXEC sp_executesql @statement = @statement