如何将数据透视表应用于查询结果
How to apply pivot to result of query
这是我当前的查询:
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"。但是我所有的尝试都失败了。我无法将我在示例中看到的内容投射到我的 table。请帮忙。
对于列数,我可以添加这样的 "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
...
在我的场景中:
- 帐户数量可能不同;
- 名称、代码和数据 - 每个查询一个;
- 账户+货币的组合是唯一的;
- 结果应在一行中;
- 查询结果的总行数,不能超过10(在我的例子中是8)
如果您知道所有账户+货币组合,您可以使用这个数据透视表(我在这里只实现了其中的 3 个):
select *
from (
<your-query> )
pivot (
min(accounts) as accounts FOR (accounts) in ('acc1+curr1' as a, 'acc2+curr1' as b, 'acc1+curr2' c)
);
根据我上面的评论,我认为 PIVOT 不适合你。 @RoundFour 的答案有效,但需要您知道并编码 Account || 的所有可能值货币。这表明这些项目永远不会有新的价值 - 我发现这不太可能。
以下将允许您切换数据的形状。它没有对数据中的 值 做出任何假设,但它确实对可能的组合数量进行了假设 - 我已经编码为八个。
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 >>>>>>>>>
上面的 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
;
这是我的关键解决方案:
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
这是我当前的查询:
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"。但是我所有的尝试都失败了。我无法将我在示例中看到的内容投射到我的 table。请帮忙。
对于列数,我可以添加这样的 "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
...
在我的场景中:
- 帐户数量可能不同;
- 名称、代码和数据 - 每个查询一个;
- 账户+货币的组合是唯一的;
- 结果应在一行中;
- 查询结果的总行数,不能超过10(在我的例子中是8)
如果您知道所有账户+货币组合,您可以使用这个数据透视表(我在这里只实现了其中的 3 个):
select *
from (
<your-query> )
pivot (
min(accounts) as accounts FOR (accounts) in ('acc1+curr1' as a, 'acc2+curr1' as b, 'acc1+curr2' c)
);
根据我上面的评论,我认为 PIVOT 不适合你。 @RoundFour 的答案有效,但需要您知道并编码 Account || 的所有可能值货币。这表明这些项目永远不会有新的价值 - 我发现这不太可能。
以下将允许您切换数据的形状。它没有对数据中的 值 做出任何假设,但它确实对可能的组合数量进行了假设 - 我已经编码为八个。
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 >>>>>>>>>
上面的 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
;
这是我的关键解决方案:
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