2017-02-20 8 views
0

Существует мой текущий запрос:Как применить пивот к результату запроса

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)
+1

Привет Павло: Я Я не уверен, что PIVOT будет работать на вас. Эта команда полезна, когда вы хотите перекрестно табулировать набор данных. Это означает использование данных в списке для создания табличной структуры - каждая ячейка содержит результат некоторой совокупной функции (SUM, COUNT и т. Д.). Нам нужно знать количество столбцов заранее (SQL всегда нужно знать количество столбцов заранее). Я предполагаю, что в вашем сценарии имя1 и name2 могут иметь разные номера учетных записей, а потому столбцы - это не сработает. Каково ваше основное требование? –

+0

Я добавил столбец «id», который перечисляет строки 1,2,3, ..., 8. И некоторые требования к сценарию. –

+0

Я добавил ответ ниже. Но меня очень интересует, почему вы хотите изменить способ хранения данных. Зачем вам данные в одной строке? –

ответ

1

На мой комментарий выше, я не думаю, что PIVOT работает на вас. Ответ от @RoundFour работает, но требует, чтобы вы знали и кодировали все возможные значения для учетной записи || Валюта. Это говорит о том, что никогда не будет новых значений для этих предметов - я нахожу это маловероятным.

Следующее позволит вам изменить форму ваших данных. В ваших данных не делается никаких предположений о значениях , но он принимает ограничение на количество возможных комбинаций - я кодировал восемь.

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 
; 

UPDATE >>>>>>>>>

С ... пункт выше только потому, что у меня нет таблиц и данных в моей системе. Я переписан мой ответ, используя запрос в качестве руководства - обратите внимание, я не был в состоянии проверить это ...

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 
; 
+0

Я не могу запустить его с помощью моего инструмента (SQL Navigator 6.2), он дает «ORA-00928: отсутствует ключевое слово SELECT» после ключевого слова «AS». Какой инструмент я могу использовать для запуска этого кода? –

+0

Это может быть проблема с пробелами - избавиться от возврата каретки, чтобы она читала AS (SELECT. Это может помочь. Я боюсь, что никогда не использовал SQL Navigator - я использую SQL Developer. –

+0

Я обновил ответ. WITH, потому что у меня нет данных в моей системе. Если это вызывает проблемы, просто игнорируйте их и используйте мой обновленный SQL. –

0

Если вы знаете, все счета + комбинации валют вы можете использовать этот стержень (I реализован только 3 из них здесь):

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

К сожалению, я не знаю: у каждого имени есть свои уникальные учетные записи. –

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