使用每列的选择性聚合从两列创建 SQL 值

Posted

技术标签:

【中文标题】使用每列的选择性聚合从两列创建 SQL 值【英文标题】:Creating SQL values from two columns using the selective aggregate of each column 【发布时间】:2021-11-01 22:40:18 【问题描述】:

我有以下四个表: region_reference、community_grants、HealthWorkers 和 currency_exchange

以及以下有效的 SQL 查询:

SELECT HealthWorkers.worker_id
  , community_grants.percentage_price_adjustment
  , community_grants.payment_status
  , community_grants.chosen
  , (region_reference.base_price * currency_exchange.euro_value) AS price
FROM currency_exchange 
  INNER JOIN (
    region_reference INNER JOIN (
      HealthWorkers INNER JOIN community_grants 
        ON HealthWorkers.worker_id = community_grants.worker_id
    ) ON (
      region_reference.community_id = community_grants.community_id
    ) AND (region_reference.region_id = community_grants.region_id)
  ) 
ON currency_exchange.currency = HealthWorkers.preferred_currency
WHERE (
  HealthWorkers.worker_id="malawi_01" 
    AND community_grants.chosen=True
);

它给了我以下结果集:

但是,我的任务是创建一个仅包含 4 个值的实体。

type OverallPriceSummary struct 
    Worker_id          string         `json:"worker_id"`
    Total_paid        decimal.Decimal `json:"total_paid"`
    Total_pledged     decimal.Decimal `json:"total_pledged"`
    Total_outstanding decimal.Decimal `json:"total_outstanding"`

Total_paid 是指定 worker_id 的值的总和,其中 payment_status = “1”(所有记录的组合)

Total_outstanding 是 payment_status 为“0”且选择为 true 的值的总和(所有记录的组合)

Total_pledged 是 Total_paid 和 Total_outstanding 的总和(所有记录也合并)

我目前通过在我的代码中手动聚合这些值来获取这些值,因为 postgresql 会遍历结果集,但我相信有一种方法可以避免这个临时 SQL 查询并从单个 SQL 查询中获得我需要的东西。 我怀疑它涉及使用 SUM AS 和内部查询,但我不知道如何将它们组合在一起。任何帮助或指导将不胜感激。

编辑: 我在下面提供了一些示例数据:

region_reference

region_id region_name base_price community_id
1 Lilongwe 100 19
2 Mzuzu 50 19

卫生工作者

worker_id worker_name preferred_currency billing_address charity_logo
malawi_01 Raphael Salanga EUR Nkhunga Health Centre in Nkhotakota District 12345

community_grants

region_id campaign_id worker_id percentage_price_adjustment community_id payment_status chosen paid_price
1 1 malawi_01 10 19 0 Yes 0
2 1 malawi_01 0 19 1 Yes 20
3 1 malawi_01 1 19 0 Yes 0
1 1 malawi_01 0 23 0 Yes 30

currency_exchange

currency currency_symbol euro_value
EUR 1
USD $ 0.84

【问题讨论】:

请在您的问题中提供一些示例数据,以及您希望使用该数据实现的结果 您的图像和 SQL 表示 MS Access,但您提到并标记了 Postgres。您是否在 Access GUI 中使用 Postgres 链接表?还是您需要直通查询?这很重要,因为 SQL 方言在 Access 和 Postgres 之间会有所不同。 @Parfait 我继承了一个 MSAccess 数据库,所以我用它来将查询放在一起,查询也适用于 Postgresql。我很高兴方言纯粹是 Postgresql 特有的。我想知道如何优化 MS Access 生成的内容也会很有用。 什么是值的总和?总价表示为:region_reference.base_price * currency_exchange.euro_value) AS price? 它稍微复杂一些,(region_reference.base_price * currency_exchange.euro_value)+(currency_exchange.euro_value*region_reference.base_price * (community_pricing.percentage_price_adjustment/100)) AS 价格,但同样的想法也适用 【参考方案1】:

考虑使用 Postgres 的 FILTER 子句进行条件聚合,在该子句中将数据透视到计算的条件列。

以下假设 值的总和 是计算价格的总和,表示为:region_reference.base_price * currency_exchange.euro_value。根据需要进行调整。

SELECT h.worker_id
   , SUM(r.base_price * ce.euro_value) FILTER(WHERE
        cg.payment_status = 1
     ) AS total_paid
   , SUM(r.base_price * ce.euro_value) FILTER(WHERE
        cg.payment_status = 0 AND 
        cg.chosen=True
     )  AS total_outstanding
   , SUM(r.base_price * ce.euro_value) FILTER(WHERE
        (cg.payment_status = 1) OR 
        (cg.payment_status = 0 AND cg.chosen=True)
     )  AS total_pledged

FROM  community_grants cg
INNER JOIN region_reference r
  ON  r.community_id = cg.community_id
  AND r.region_id = cg.region_id
INNER JOIN HealthWorkers h
  ON  h.worker_id = cg.worker_id
  AND h.worker_id = 'malawi_01'
INNER JOIN currency_exchange ce
  ON ce.currency = h.preferred_currency

GROUP BY h.worker_id

【讨论】:

我需要在每次使用 Filter 的地方添加 FILTER( 但效果很好 哎呀!谢谢你的忽视。相应地进行了编辑。或者,使用CASE(可移植到其他RDBMS)但不幸的是不能访问yet【参考方案2】:

尝试类似:

SELECT
worker_id
,sum(case when payment_status = “1” 
      then paid_price else 0 end) as Total_paid
,sum(case when payment_status = “0” and chosen = true
      then paid_price else 0 end) as Total_outstanding
,sum(case when (payment_status = “1”) 
     or (payment_status = “0” and chosen = true)
      then paid_price else 0 end) as Total_pledged
from community_grants
group by worker_id

【讨论】:

刚刚意识到这会跳过其他表的链接

以上是关于使用每列的选择性聚合从两列创建 SQL 值的主要内容,如果未能解决你的问题,请参考以下文章

pandas 选择每列的最小值和最大值并创建一个新的数据框

SQL Server:在具有两列的表上进行无聚合的旋转

从两列中选择非不同的行

MySQL - 从两列中选择不同的值

MYSQL:从两列中选择最高的ID并排序

根据两列的值选择熊猫数据框行