英文:
I need to separate a PostgreSQL table in this intercalated format
问题
我在Postgres中有这个查询:
Select
"Charges"."saleAmount", "Charges"."buyAmount", "Operations"."id"
From
"Charges"
Left Join
"Operations" On "Operations"."id" = "Charges"."operationsId"
Order By
"Operations"."id"
我需要将它转换成这样的格式:根据saleAmount
> 0或buyAmount
> 0添加一个新列type
,并在同一行中同时具有saleAmount
和buyAmount
时将其拆分为两行。
type
列可以使用以下方式创建:
(CASE
WHEN "saleAmount" > 0 THEN 'sale'
WHEN "buyAmount" > 0 THEN 'buy'
END) as "type"
如何将我的表格转换成这种格式?
英文:
I have this query in Postgres:
Select
"Charges"."saleAmount", "Charges"."buyAmount", "Operations"."id"
From
"Charges"
Left Join
"Operations" On "Operations"."id" = "Charges"."operationsId"
Order By
"Operations"."id"
saleAmount | buyAmount | id |
---|---|---|
200 | NULL | id1 |
300 | 500 | id2 |
0 | 100 | id3 |
I need to transform it: Add a new column type
depending on saleAmount
> 0 or buyAmount
> 0, and separate into two rows when I have both saleAmount
and buyAmount
in the same row.
saleAmount | buyAmount | id | type |
---|---|---|---|
200 | NULL | id1 | sale |
300 | 0 | id2 | sale |
0 | 500 | id2 | buy |
0 | 100 | id3 | buy |
How do I transform my table into this format?
Column type
can be made with:
(CASE
WHEN "saleAmount" > 0 THEN 'sale'
WHEN "buyAmount" > 0 THEN 'buy'
END) as "type"
答案1
得分: 1
你可以使用 UNION ALL
来将一个行拆分成两行。例如:
选择 c."saleAmount", c."buyAmount", o."id", c.type
从
(
选择
"saleAmount",
情况 当 "buyAmount" > 0 然后 0 否则 "buyAmount" 结束为 "buyAmount",
'sale' 作为类型
从 "Charges"
其中 "saleAmount" > 0
联合全部
选择
情况 当 "saleAmount" > 0 然后 0 否则 "saleAmount" 结束为 "saleAmount",
"buyAmount",
'buy' 作为类型
从 "Charges"
其中 "buyAmount" > 0
) c
左连接 "Operations" o 在 o."id" = c."operationsId"
按 o."id" 排序;
顺便说一下,Operations表的连接似乎是多余的。要么Charges具有operationsId,然后它链接到具有相同ID的Operations行,要么它没有operationsId,然后它不链接到Operations行。那么为什么不只显示"Charges"."operationsId",而不是连接到Operations表,只是为了显示相同的ID?
英文:
You can use UNION ALL
to create two rows out of one. E.g.:
Select c."saleAmount", c."buyAmount", o."id", c.type
From
(
Select
"saleAmount",
Case When "buyAmount" > 0 Then 0 Else "buyAmount" End As "buyAmount",
'sale' as type
From "Charges"
Where "saleAmount" > 0
Union All
Select
Case When "saleAmount" > 0 Then 0 Else "saleAmount" End As "saleAmount",
"buyAmount",
'buy' as type
From "Charges"
Where "buyAmount" > 0
) c
Left Join "Operations" o On o."id" = c."operationsId"
Order By o."id";
The join of the Operations table seems superfluous by the way. Either the Charges has an operationsId, then it links to an Operations row with the same ID or it doesn't have an operationsId, then it doesn't link to Operations row. So why not just show the "Charges"."operationsId" instead of joining to the Operations table just to show the same ID?
答案2
得分: 0
你可以加入一个values表构造器,并使用一个条件表达式来确定有多少行符合连接条件:
select t.*
from t
join (
values(1),(2)
)x(r) on r <= case
when Coalesce(saleamount, 0) > 0
and Coalesce(buyAmount, 0) > 0
then 2 else 1 end;
英文:
You can join to a values table constructor and use a case expression to determine how many rows qualify for the join:
select t.*
from t
join (
values(1),(2)
)x(r) on r <= case
when Coalesce(saleamount, 0) > 0
and Coalesce(buyAmount, 0) > 0
then 2 else 1 end;
答案3
得分: 0
我认为你可以使用union all。
select
c.saleAmount,
0 buyAmount,
o.id,
'sale'
from Charges c
Left Join "Operations" o On o."id" = c."operationsId"
where isnull(c.saleAmount) > 0
union all
select
0 saleAmount,
c.buyAmount,
o.id,
'buy'
from Charges c
Left Join "Operations" o On o."id" = c."operationsId"
where isnull(c.buyAmount,0) > 0
英文:
I think you can use union all.
select
c.saleAmount,
0 buyAmount,
o.id,
'sale'
from Charges c
Left Join "Operations" o On o."id" = c."operationsId"
where isnull(c.saleAmount) > 0
union all
select
0 saleAmount,
c.buyAmount,
o.id,
'buy'
from Charges c
Left Join "Operations" o On o."id" = c."operationsId"
where isnull(c.buyAmount,0) > 0
答案4
得分: 0
在Postgres中,您可以使用values
和lateral join
将两列转换为行,然后在where
子句中过滤掉不需要的行:
select c.*, t.type
from charges c
cross join lateral (
values (c.saleamount, 'sale'), (c.buyamount, 'buy')
) t(amount, type)
where t.amount > 0
原始查询中的left join
的目的不明显,所以我将其留了出来,但如果需要的话,您可以轻松将其添加到查询中。
英文:
In Postgres you can unpivot the two columns to rows with values
and a lateral join, then filter out unwanted rows in the where
clause:
select c.*, t.type
from charges c
cross join lateral (
values (c.saleamount, 'sale'), (c.buyamount, 'buy')
) t(amount, type)
where t.amount > 0
It is not obvious what the purpose of the left join
in the original query is, so I left it apart - but you can easily add it to the query if needed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论