解释以下查询的工作原理?

时间:2011-05-29 12:34:20

标签: mysql join aggregate-functions

我有一个以奇怪方式工作的mysql查询。我发布了2个查询,输入数据已更改,输出列在每个查询下。

查询1(要注意的区域BETWEEN '13/05/11' AND '30/05/11'):

SELECT COUNT(pos_transaction_id) AS total,
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date,
SUM(amount) AS amount
FROM pos_transactions pt 
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN '13/05/11' AND '30/05/11'
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp

输出:
enter image description here

查询2(要注意的区域BETWEEN '3/05/11' AND '30/05/11'):

SELECT COUNT(pos_transaction_id) AS total,
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date,
SUM(amount) AS amount
FROM pos_transactions pt 
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN '3/05/11' AND '30/05/11'
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp

输出:
enter image description here 现在,当第二个查询中的范围增加时,为什么我只获得一条记录?即使在第一个查询中,我也会收到超出范围的记录。这有什么问题?

修改

更改的查询看起来像这样,仍然没有按照我的意愿去做。

SELECT COUNT(pos_transaction_id) AS total,
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date,
SUM(amount) AS amount
FROM pos_transactions pt
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN STR_TO_DATE('01/05/11','%e/%m/%y') AND STR_TO_DATE('30/05/11','%e/%m/%y')
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp

输出是: enter image description here

3 个答案:

答案 0 :(得分:1)

我绝对不确定,但可能比较是以string而非日期进行的。

DATE_FORMAT返回string,您的条件也是字符串。

您应该在没有DATE_FORMAT的情况下尝试,只需要尝试将条件转换为日期。

我在想这样的事情:

pt.timestamp BETWEEN STR_TO_DATE('13/05/11', '%e/%m/%y') AND STR_TO_DATE('30/05/11', '%e/%m/%y')

答案 1 :(得分:1)

我很确定你有意义

WHERE pt.timestamp BETWEEN TO_DATE('13/04/11', 'dd/mm/yy') AND TO_DATE('30/05/11', 'dd/mm/yy')

在你要求两个字符串之间的字符串之前。

<强>更新

我认为这里错过了一些观点。根据您在pos_transactions.timestamp进行的计算,我将假设它是timestamp的类型。在查询中,如果要进行范围比较,则需要直接使用时间戳。时间戳已包含进行此比较所需的所有数据。您无需将其转换为日/月/年进行比较。

您需要做的是:

查找我的timestamp介于create a new date from '13/05/11'create a new date from '30/05/11'之间的所有值。 pt.timestamp已经是一个时间戳,无需在WHERE子句中转换它。

您一直在做的是将其转换为String表示形式。如果你想要显示它,那就好了,但是当你想要将它与其他值进行比较时却没有。

答案 2 :(得分:1)

我认为你看到了两种不良做法的结果。

首先,date_format()函数返回一个字符串。您的WHERE子句进行字符串比较。在PostgreSQL中

select '26/04/2011' between '13/05/11' AND '30/05/11';
--
T

那是因为字符串'26'在字符串'13'和'30'之间。但是,如果您将它们写为日期,PostgreSQL会正确地告诉您“2011-04-26”(在我的服务器上的日期样式设置之后)不在该范围内。

其次,我猜测会出现奇怪的超出范围的值,因为您在聚合中使用了一个不确定的表达式。表达式WEEK(pt.timestamp)未出现在SELECT列表中。我认为如果你试图这样做,市场上的每一个SQL引擎都会抛出一个错误。由于它不在SELECT列表中,MySQL将从该聚合范围返回一个明显随机的值。

要避免这些类型的错误,请不要对日期或时间戳范围进行字符串比较,也不要使用不确定的聚合表达式。

发布DDL和最小的SQL INSERT语句来重现问题有助于人们为您提供帮助。