如何使用具有不同 where 条件的多项选择获得结果

Posted

技术标签:

【中文标题】如何使用具有不同 where 条件的多项选择获得结果【英文标题】:How get results using multiple selects with different where condition 【发布时间】:2019-10-22 15:44:10 【问题描述】:

我有四个表 customers、orders、orderitems 和 sales,我想获取每个客户的应付总额以及每个客户的余额。为此,我尝试了这个 SQL 查询:

SELECT c.name          AS CustomerName, 
       c.contactnumber AS CustomerContactNumber, 
       c.location      AS CustomerAddress, 
       SUM(oi.amount)  AS Amount, 
       SUM(t2.balance) AS Balance 
FROM   orderitems oi 
INNER JOIN orders o ON oi.orderid = o.id 
INNER JOIN customers c ON o.customerid = c.id 
INNER JOIN
    (SELECT s.customerid, 
            SUM(s.balance) AS Balance 
     FROM   sales s 
     INNER JOIN customers c ON s.customerid = c.id 
     GROUP BY s.customerid) t2 ON t2.customerid = c.id 
WHERE o.status == 'Processing' 
GROUP BY 
    c.id, c.contactnumber, c.location 

它生成以下输出:

它正确计算了应付金额,但它计算了两次余额,因为两个客户的原始余额都是 100,但每个客户都显示 200。

另外请注意,订单有一个状态栏,如果订单金额到期,则显示“处理中”,如果有余额,则显示“未完成”。

表结构是:

订单:

销售:

订单项:

客户:

请帮忙。

【问题讨论】:

每个Curstomer 有多个ContactNumber 还是多个Location 不,每个客户都有一条记录,当订单处理完毕时,我会在销售表中保存已支付的余额,并根据订单表中的余额将订单状态从处理更新为完成/未完成。 向我们展示数据库架构、示例数据、当前和预期输出。请阅读How-to-Ask 提示:为数据库问题“显示”架构的最佳方式是包含 CREATE TABLE 语句,而不是图像,尤其是链接图像。 每个客户有多少订单?是 2 吗?为什么你在加入 sum(balance) 的过程中,然后又在顶层做 sum。虽然不看数据很难确定,但在我看来,如果客户有多个订单项,这个查询是不正确的。 【参考方案1】:

这行得通吗?

SELECT c.name          AS CustomerName, 
       c.contactnumber AS CustomerContactNumber, 
       c.location      AS CustomerAddress, 
       SUM(oi.amount)  AS Amount, 
       SUM(s.balance) AS Balance 
FROM   orderitems oi 
INNER JOIN orders o ON oi.orderid = o.id 
INNER JOIN customers c ON o.customerid = c.id 
INNER JOIN sales s on c.id = s.customerid
WHERE o.status == 'Processing' 
GROUP BY 
    c.id, c.contactnumber, c.location 

【讨论】:

@CPerkins 我猜。还指出这在功能上与当前代码相同。 @CPerkins -- 这是一个公平的观点 -- 有时人们发布的内容不是他们实际运行的内容(例如,他们简化了发布内容)并且它显示了他们的原始查询是如何不正确的(如这里有一个不需要的子查询。)老实说,我真的没有充分的理由,有时我会随机 shjt 看看有什么效果。【参考方案2】:

您正在对外部查询中的余额求和,但您不应该这样做,因为它是在子查询中求和的。您可以按余额分组(这不是很好的设计理论,但它很实用);或者您可以对总和(金额)进行单独的子查询,然后然后加入余额而不分组。

SELECT c.name          AS CustomerName, 
       c.contactnumber AS CustomerContactNumber, 
       c.location      AS CustomerAddress, 
       SUM(oi.amount)  AS Amount, 
       t2.balance      AS Balance
FROM   orderitems oi 
INNER JOIN orders o ON oi.orderid = o.id 
INNER JOIN customers c ON o.customerid = c.id 
INNER JOIN (
   SELECT customerid, SUM(balance) AS Balance
   FROM   sales
   GROUP BY customerid
) t2 ON t2.customerid = c.id 
WHERE o.status == 'Processing' 
GROUP BY c.id, c.contactnumber, c.location, c.name, t2.balance

作为 2 个子查询:

SELECT c.name          AS CustomerName, 
       c.contactnumber AS CustomerContactNumber, 
       c.location      AS CustomerAddress, 
       t3.Amount       AS Amount,
       t2.balance      AS Balance
FROM   customers c
INNER JOIN ( -- subquery to return Amount for each customerid
   select o.customerid, sum(oi.amount) AS Amount
   FROM orderitems oi
   INNER JOIN orders o ON oi.orderid = o.id 
   GROUP BY o.customerid
   WHERE o.status == 'Processing'
) t3 on t3.cusomterid = c.id
INNER JOIN ( -- subquery to return balance for each customerid
   SELECT customerid, SUM(balance) AS Balance
   FROM   sales
   GROUP BY customerid
) t2 ON t2.customerid = c.id 

【讨论】:

如果每个客户有多个余额/销售额按余额分组,那么计算余额是有意义的,这对我来说似乎永远不正确。 只求和一次才有意义——这是在子查询中完成的。再次相加将有效地将余额乘以订单数量。 子查询的结果应该只有一行——它有一个分组依据——所以外部总和应该没有影响AFAICT 客户的余额是内部连接到每个订单项目的。然后当它稍后再次分组并再次求和时,它将乘以项目总数(不是订单,正如我之前所说)。

以上是关于如何使用具有不同 where 条件的多项选择获得结果的主要内容,如果未能解决你的问题,请参考以下文章

如何获得具有指定 where 条件的所有多对一行?

如何分隔不同列中的多项选择短语(谷歌表单)?

如何从其他地方选择具有不同 WHERE 语句的东西

选择具有不同 where 条件的同一列

如何从views.py中的模板中获得多项选择

具有多个 where 子句的选择查询在一个结果表中返回多个结果行?