选择选择的位置?

时间:2016-02-08 11:15:50

标签: mysql sql database select

我有一个查询,找到所有未完成余额不等于0的人。我虽然一切都好,但扩大了可用的样本数据,我发现它不完全存在(我想不远)。

代码如下:

    SELECT bookingRef, leadname, departureDate, balanceDueDate,
      totalDue, totalReceived, (totalDue - totalReceived) AS outstandingBalance,
      (SELECT SUM(CASE WHEN(totalDue - totalReceived) <> 0 THEN 1 ELSE 0 END)
       FROM bookings) AS numberOutstanding,
      (SELECT SUM(totalDue) FROM bookings) AS grossDue,
      (SELECT SUM(totalReceived) FROM bookings) AS grossReceived,
      (SELECT SUM(totalDue - totalReceived) FROM bookings) AS grossOutstanding
    FROM bookings
    WHERE (amendedDate BETWEEN '2015-09-30' AND '2016-09-30')
    HAVING outstandingBalance <> 0;

当日期在整个范围内时,结果是正确的,会发生什么。然而,如上所述仅做一年时,它仍然总计了总范围,忽略了总和的where子句。

我认为我需要为每个sum选择添加where子句,但仍然会遇到运行错误。

我将如何实现这一目标。

非常感谢

注意:MySQL非常生疏(8-10岁而不使用它)。

1 个答案:

答案 0 :(得分:1)

没有窗口功能的解决方案(适用于MySQL)

不幸的是,MySQL不支持窗口函数,这对于这个查询来说会更方便。相反,您可以在您的案例中使用交叉连接。但是,你不会四次应用谓词,因为MySQL也不支持公共表表达式:

SELECT b.bookingRef, b.leadname, b.departureDate, b.balanceDueDate,
  b.totalDue, b.totalReceived, (b.totalDue - b.totalReceived) AS outstandingBalance, a.*
FROM bookings b,
CROSS JOIN (
  SELECT 
    SUM(CASE WHEN(totalDue - totalReceived) <> 0 THEN 1 ELSE 0 END AS numberOutstanding,
    SUM(totalDue) AS grossDue,
    SUM(totalREceived) AS grossReceived,
    SUM(totalDue - totalReceived) AS grossOutstanding
  FROM bookings
  WHERE (amendedDate BETWEEN '2015-09-30' AND '2016-09-30')
  AND (totalDue - totalReceived) <> 0
) a
WHERE (b.amendedDate BETWEEN '2015-09-30' AND '2016-09-30')
AND (b.totalDue - b.totalReceived) <> 0;

或者,您也可以将谓词复制到SELECT子句中的每个子查询中,但这种方法可能会更糟糕。

具有窗口函数的解决方案

为了完整起见,在大多数其他数据库中,您将改为编写此查询:

SELECT bookingRef, leadname, departureDate, balanceDueDate,
  totalDue, totalReceived, (totalDue - totalReceived) AS outstandingBalance,
  SUM(CASE WHEN(totalDue - totalReceived) <> 0 THEN 1 ELSE 0 END) OVER() AS numberOutstanding,
  SUM(totalDue) OVER() AS grossDue,
  SUM(totalReceived) OVER() AS grossReceived,
  SUM(totalDue - totalReceived) OVER() AS grossOutstanding
FROM bookings
WHERE (amendedDate BETWEEN '2015-09-30' AND '2016-09-30')
AND (b.totalDue - b.totalReceived) <> 0;

关于HAVING

的附注

我怀疑您正在使用HAVING子句,以便能够重用SELECT子句中的列名。这是特定于MySQL的,可能并不完全符合您的预期。 HAVINGGROUP BY 之后应用(因此,在汇总之后)。在您的查询中,您真的不需要GROUP BY子句,因此我会避免使用HAVING