我需要将一个 PostgreSQL 表按照这种交错的格式分开。

huangapple go评论66阅读模式
英文:

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,并在同一行中同时具有saleAmountbuyAmount时将其拆分为两行。

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 &lt;= case 
    when Coalesce(saleamount, 0) &gt; 0
     and Coalesce(buyAmount, 0) &gt; 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,
  &#39;sale&#39;
from Charges c
  Left Join &quot;Operations&quot; o On o.&quot;id&quot; = c.&quot;operationsId&quot;
where isnull(c.saleAmount) &gt; 0
union all
select
  0 saleAmount,
  c.buyAmount,
  o.id,
  &#39;buy&#39;
from Charges c
  Left Join &quot;Operations&quot; o On o.&quot;id&quot; = c.&quot;operationsId&quot;
where isnull(c.buyAmount,0) &gt; 0

答案4

得分: 0

在Postgres中,您可以使用valueslateral 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, &#39;sale&#39;), (c.buyamount, &#39;buy&#39;)
) t(amount, type)
where t.amount &gt; 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.

huangapple
  • 本文由 发表于 2023年1月9日 04:57:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051243.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定