PostgreSQL从行中创建新表

时间:2013-10-03 13:40:46

标签: sql postgresql pivot

我正在使用PostgreSQL 9.1

我有下表包含一些设置

      setting    | content 
  ---------------+---------
   enabled       | True
   reenable_time | 1
   count_row     | 6
   count_col     | 3
  (4 rows)

我希望有这样的东西

enabled  |  reenable_time  |  count_row  |  count_col
---------+-----------------+-------------+----------
True     |  1              |      6      |  3
(1 row)

感谢您的回答!

1 个答案:

答案 0 :(得分:1)

您需要的是交叉制表(旋转),即将行转换为列。

如果您不想硬编码“enabled”,“reenable_time”等,则需要使用动态SQL。

基本理念是这样的:

SELECT -- Grab the user_account columns.
       acc.id,
       acc.email,
       -- Use max() combined with a case statement to
       -- usher individual attribute values into columns.
       max(CASE WHEN (attr.attribute_type = 'first-name')
                THEN attr.value END) AS fname,
       max(CASE WHEN (attr.attribute_type = 'last-name')
                THEN attr.value END) AS lname,
       max(CASE WHEN (attr.attribute_type = 'title')
                THEN attr.value END) AS title
   FROM user_account AS acc
   -- Join the attribute table /once/.
   LEFT JOIN user_attribute AS attr
     ON (attr.user_account_id = acc.id)
   WHERE (acc.email = 'foo@example.com')
   -- Group by the non-pivoted columns
   GROUP BY acc.id,acc.email;

此处提供了更多信息的链接:
https://sykosomatic.org/2011/09/pivot-tables-in-postgresql/

这是我工作场所的一个例子(它是MS-SQL,但是你会明白,PostGre不支持pivot命令,它是MS专有的,所以你需要使用“case when”和“group by” ):

-- ===================================================
-- Author:        Stefan Steiger
-- Create date:   14.04.2011
-- Last modified: 17.01.2012
-- Description:   Übersetzung für Berichte
-- ===================================================
CREATE PROCEDURE [dbo].[sp_RPT_Report_Translation]
     @in_mandant varchar(3) 
    ,@in_sprache varchar(2) 
    ,@in_stichtag varchar(50) 
    ,@in_report_name nvarchar(1000) 
AS
BEGIN
    DECLARE 
     @strSQL NVARCHAR(MAX) 
    ,@strReportName NVARCHAR(1000) 
    ,@strPivotColumns NVARCHAR(MAX) 
    ,@stichtag DATETIME 


    -- Abrunden des Eingabedatums auf 00:00:00 Uhr 
    SET @stichtag    = CONVERT(DATETIME, @in_stichtag) 
    SET @stichtag    = CAST(FLOOR(CAST(@stichtag AS Float)) AS DateTime) 
    SET @in_stichtag = CONVERT(varchar(50), @stichtag) 

    SET NOCOUNT ON;

    SET @strReportName = REPLACE(@in_report_name, N'''', '''''') 

    -- http://geekswithblogs.net/baskibv/archive/2008/07/03/123567.aspx
    SELECT 
        @strPivotColumns = COALESCE(@strPivotColumns, '') + '[' + [RTR_ItemCaption] + '], ' 
    FROM T_RPT_Translations 
    WHERE (RTR_Status = 1) 
        AND (RTR_MDT_ID = @in_mandant) 
        AND 
        ( 
            (RTR_ReportName = @strReportName) 
            OR 
            (RTR_ReportName = 'PARA_ALL') 
        ) 
        --AND (RTR_ItemCaption != 'RPT_Title') 
        AND (RTR_ItemCaption IS NOT NULL) 
        AND 
        (
                (RTR_IsFlag != 1) 
                OR 
                (RTR_IsFlag IS NULL) 
        ) 
        AND (RTR_ItemCaption != '') 
    ORDER BY RTR_Sort



    SET @strPivotColumns = SUBSTRING(@strPivotColumns, 0, LEN(@strPivotColumns)) 
    SET @strPivotColumns = REPLACE(@strPivotColumns, N'''', '''''') 

    --PRINT @strPivotColumns

    SET @strSQL = '
        SELECT TOP(1) * FROM 
        ( 
            SELECT 
                 RTR_ItemCaption 
                --,RTR_Kurz_' + @in_sprache + ' 
                ,RTR_Lang_' + @in_sprache + ' 
            FROM T_RPT_Translations 
            WHERE (RTR_MDT_ID = ''' + @in_mandant+ ''') 
                AND
                ( 
                    (RTR_ReportName = ''' + @strReportName + ''') 
                    OR 
                    (RTR_ReportName = ''PARA_ALL'')
                )
                --AND (RTR_ItemCaption != ''RPT_Title'') 
                AND (RTR_Status = 1) 
                AND (RTR_ItemCaption IS NOT NULL)
                AND 
                (
                    (RTR_IsFlag != 1) 
                    OR 
                    (RTR_IsFlag IS NULL) 
                ) 
                AND (RTR_ItemCaption != '''')  

        ) AS SourceTable 
        PIVOT 
        ( 
            MAX(RTR_Lang_' + @in_sprache + ') 
            FOR RTR_ItemCaption IN 
            ( ' 
                + @strPivotColumns + 
          ' ) 

        ) AS PivotTable 

        --ORDER BY RPT_RM_SO_Bezeichnung, RPT_RM_GB_Bezeichnung, RPT_RM_NutzungGruppeCode 
    ' 

    DECLARE @ProzedurParameter nvarchar(max)
    SET @ProzedurParameter = '
    DECLARE @in_mandant varchar(3) 
    ,@in_sprache varchar(2) 
    ,@in_stichtag varchar(50) 
    ,@in_report_name nvarchar(1000) 
    ;

    SET @in_mandant = ''' + REPLACE(@in_mandant, '''', '''''') + '''; 
    SET @in_sprache = ''' + REPLACE(@in_sprache, '''', '''''') + '''; 
    SET @in_stichtag = ''' + REPLACE(@in_stichtag, '''', '''''') + '''; 
    SET @in_report_name = ''' + REPLACE(@in_report_name, '''', '''''') + '''; 
    '



    EXECUTE sp_RPT_DEBUG_LOG_ProzedurRun 
        'sp_RPT_Report_Translation'
        ,@ProzedurParameter
        ,@strSQL 
        ,'' --@ProzedurDetail
    ;


    --PRINT @strSQL
    EXECUTE (@strSQL)

END



GO