如何将pivot应用于查询结果

时间:2017-02-20 13:24:19

标签: sql oracle pivot

我目前有疑问:

SELECT Name, Code, Today
    , Account || Currency as Accounts
FROM (
    SELECT
          b.description AS Name
        , b.contragentidentifycode AS Code
        , c.systemday AS Today
        , b.accountno AS Account
        , b.currencysname AS Currency
    FROM vAACCOUNT b, currentdaysetting c
    WHERE b.contragentid = 412
    AND b.accountno LIKE '26%' 
)

它给了我这样的结果:

Name  | Code  | Today      | Accounts
---------------------------------------
name1 | code1 | 07.09.2016 | acc1+curr1
name1 | code1 | 07.09.2016 | acc2+curr1
name1 | code1 | 07.09.2016 | acc1+curr2       
name1 | code1 | 07.09.2016 | acc2+curr2       
name1 | code1 | 07.09.2016 | acc1+curr3            
name1 | code1 | 07.09.2016 | acc2+curr3            
name1 | code1 | 07.09.2016 | acc1+curr4
name1 | code1 | 07.09.2016 | acc2+curr4

我需要将此视图转换为:

Name  | Code  | Today      | someName1  |  someName2  |  someName3  |  someName4  |  someName5  |  someName6  |  someName7  |  someName8
-------------------------------------------------------------------------------------------------------------------------------------------
name1 | code1 | 07.09.2016 | acc1+curr1 | acc2+curr1  | acc1+curr2  | acc2+curr2  | acc1+curr3  | acc2+curr3  | acc1+curr4  | acc2+curr4

我想最有可能的是,我必须使用关键字“Pivot”。但我所有这样做的尝试都失败了。我无法将我在示例中看到的内容投影到我的表格中。请帮忙。

对于列数,我可以添加这样的“id”列:

SELECT id, Name, Code, Today
    , Account || Currency as Accounts
FROM (
    SELECT
         row_number() over (ORDER BY b.id) AS id
        , b.description AS Name
        ...

在我的场景中:

  • 帐号数量可能不同;
  • 名称,代码和数据 - 每个查询一个;
  • accaunt + currency的组合是唯一的;
  • 结果应该在一行;
  • 查询结果中的总行数,不能超过10(在我的例子中为8)

3 个答案:

答案 0 :(得分:1)

根据我上面的评论,我不认为PIVOT适合你。 @RoundFour的答案有效,但要求您知道并编码Account ||的所有可能值货币。这表明这些项目永远不会有新的价值 - 我觉得这不太可能。

以下内容可让您切换数据的形状。它没有对数据中的做出任何假设,但它确实假设了可能组合数量的限制 - 我编码了8个。

WITH account_data (name,code,today,account) 
AS
 (
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc1+curr1' FROM dual UNION ALL
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc2+curr1' FROM dual UNION ALL
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc1+curr2' FROM dual UNION ALL     
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc2+curr2' FROM dual UNION ALL       
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc1+curr3' FROM dual UNION ALL            
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc2+curr3' FROM dual UNION ALL            
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc1+curr4' FROM dual UNION ALL
 SELECT 'name1','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc2+curr4' FROM dual UNION ALL
 SELECT 'name2','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc1+curr1' FROM dual UNION ALL
 SELECT 'name2','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc2+curr1' FROM dual UNION ALL
 SELECT 'name2','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc1+curr2' FROM dual UNION ALL     
 SELECT 'name3','code1',TO_DATE('07.09.2016','DD.MM.YYYY'),'acc2+curr2' FROM dual 
 )
SELECT
 name
,code
,today
,MAX(account1)
,MAX(account2)
,MAX(account3)
,MAX(account4)
,MAX(account5)
,MAX(account6)
,MAX(account7)
,MAX(account8)
FROM
 (SELECT 
   name
  ,code
  ,today
  ,CASE
    WHEN rn = 1 THEN account
   END                             account1
  ,CASE
    WHEN rn = 2 THEN account
   END                             account2
  ,CASE
    WHEN rn = 3 THEN account
   END                             account3
  ,CASE
    WHEN rn = 4 THEN account
   END                             account4
  ,CASE
    WHEN rn = 5 THEN account
   END                             account5
  ,CASE
    WHEN rn = 6 THEN account
   END                             account6
  ,CASE
    WHEN rn = 7 THEN account
   END                             account7
  ,CASE
    WHEN rn = 8 THEN account
   END                             account8
  FROM
   (SELECT
    name 
   ,code
   ,today
   ,account
   ,ROW_NUMBER() OVER (PARTITION BY name ORDER BY account)   rn
   FROM
    account_data
   )
  )
GROUP BY
 name
,code
,today
;
  

更新>>>>>>>>>>

上面的WITH ...条款只是因为我的系统中没有表格和数据。我使用您的查询作为指南重写了我的答案 - 请注意我无法对此进行测试......

SELECT
 name
,code
,today
,MAX(account1)
,MAX(account2)
,MAX(account3)
,MAX(account4)
,MAX(account5)
,MAX(account6)
,MAX(account7)
,MAX(account8)
FROM
 (SELECT 
   name
  ,code
  ,today
  ,CASE
    WHEN rn = 1 THEN account
   END                             account1
  ,CASE
    WHEN rn = 2 THEN account
   END                             account2
  ,CASE
    WHEN rn = 3 THEN account
   END                             account3
  ,CASE
    WHEN rn = 4 THEN account
   END                             account4
  ,CASE
    WHEN rn = 5 THEN account
   END                             account5
  ,CASE
    WHEN rn = 6 THEN account
   END                             account6
  ,CASE
    WHEN rn = 7 THEN account
   END                             account7
  ,CASE
    WHEN rn = 8 THEN account
   END                             account8
  FROM
   (SELECT
     b.description AS Name
    ,b.contragentidentifycode AS Code
    ,c.systemday AS Today
    ,b.accountno AS Account
    ,b.currencysname AS Currency
    ,b.accountno || b.currencysname AS Accounts
    ,ROW_NUMBER() OVER (PARTITION BY b.description ORDER BY b.accountno)   rn
    FROM vAACCOUNT b, currentdaysetting c
    WHERE b.contragentid = 412
    AND b.accountno LIKE '26%' 
   )
  )
GROUP BY
 name
,code
,today
;

答案 1 :(得分:0)

如果你知道所有帐户+货币组合,你可以使用这个支点(我这里只实现了3个):

select *
from (
    <your-query>    )
pivot  (
    min(accounts) as accounts FOR (accounts) in ('acc1+curr1' as a, 'acc2+curr1' as b, 'acc1+curr2' c)
    );

答案 2 :(得分:0)

有我的支点解决​​方案:

SELECT *
FROM (
    SELECT id, Name, Code, Today, Account || Currency as Accounts
    FROM (
        SELECT
              row_number() over (ORDER BY b.id) AS id
            , b.description AS Name
            , b.contragentidentifycode AS Code
            , c.systemday AS Today
            , b.accountno AS Account
            , b.currencysname AS Currency
        FROM vAACCOUNT b, currentdaysetting c
        WHERE b.contragentid = 412
        AND b.accountno LIKE '26%' 
    )
)
pivot (
    MIN(Accounts)
    FOR ID  IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
) pvt