【问题标题】:SQL return results only if all rows match in join仅当连接中的所有行都匹配时,SQL 才返回结果
【发布时间】:2021-12-25 15:38:55
【问题描述】:

我有以下表格

table name               column names
-----------              ------------------------
delivery_ service        svc_name | svc_cost
product                  prod_id 
service_prod             svc_name | prod_id
order                    order_id
order_item               order_id | prod_id

现在我想计算订单中所有商品的总配送服务成本 (svc_cost)。当然,只有当订单中的所有商品都符合该送货服务的条件时,这个总数才有意义

例如,产品fresh tomatos 仅有express 送货服务,而产品dvd 同时拥有expressnormal shipping 作为送货服务。因此,包含 fresh tomatosdvd 项目的订单的配送成本应仅考虑 express 配送服务成本,因为 normal shipping 不符合订单总额的条件。

我不确定我应该如何将它翻译成 SQL。

欢迎任何关于从哪里开始的提示

【问题讨论】:

  • 当订单中的所有商品的服务不同时,您没有提到预期的结果。提供一个完整的测试用例,CREATE TABLE 语句,INSERT 语句,只需要足够的行来显示您关心的用例。然后根据该数据显示您期望的确切结果。提供您尝试过的任何 SQL 以及相应的错误结果。这是起点,一个完整的测试用例,因此您可以评估您的逻辑。
  • 如果所有商品都支持所有配送方式怎么办?
  • 如果只有两种送货方式“快递”和“普通”,那么据我所知,这将是 2 捆。第一个捆绑包包含所有具有“快速”的捆绑包,第二个捆绑包用于仅包含“普通”的捆绑包。正确的?但是如果没有只有“快递”的非,那么都发送“正常”呢?呃,这不是一个简单的 SQL 难题。
  • 这确实需要一个Minimal, Reproducible Example,其中包含示例数据和预期结果。

标签: sql postgresql exists full-outer-join


【解决方案1】:

只是一个未经测试的记事本涂鸦,期待澄清。

SELECT order_id, product_count
, CASE
  WHEN strictly_express_cost = 0 THEN strictly_normal_cost + whatever_normal_cost
  WHEN strictly_normal_cost = 0 THEN strictly_express_cost + whatever_express_cost
  ELSE strictly_express_cost + strictly_normal_cost + whatever_normal_cost
  END AS total_cost
FROM
(
    SELECT order_id
    , SUM(CASE WHEN express_cost > 0 AND normal_cost = 0 THEN express_cost ELSE 0 END) AS strictly_express_cost
    , SUM(CASE WHEN express_cost = 0 AND normal_cost > 0 THEN normal_cost ELSE 0 END) AS strictly_normal_cost
    , SUM(CASE WHEN express_cost > 0 AND normal_cost > 0 THEN express_cost ELSE 0 END) AS whatever_express_cost
    , SUM(CASE WHEN express_cost > 0 AND normal_cost > 0 THEN normal_cost ELSE 0 END) AS whatever_normal_cost
    , COUNT(DISTINCT prod_id) AS product_count
    FROM
    (
      SELECT orditm.order_id, orditm.prod_id
      , SUM(CASE WHEN svcprd.svc_name = 'express' THEN dlvsvc.svc_cost ELSE 0 END) AS express_cost
      , SUM(CASE WHEN svcprd.svc_name = 'normal' THEN dlvsvc.svc_cost ELSE 0 END) AS normal_cost
      FROM order_item AS orditm
      LEFT JOIN service_prod AS svcprd 
        ON svcprd.prod_id = orditm.prod_id
      LEFT JOIN delivery_service AS dlvsvc 
        ON dlvsvc.svc_name = svcprd.svc_name
      GROUP BY orditm.order_id, orditm.prod_id
    ) q1
    GROUP BY order_id
) q2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多