2011-05-29 77 views
1

我有一個奇怪的方式工作的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

回答

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語句來重現問題可以幫助人們幫助您。

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') 
+0

檢查我的編輯我仍然有問題..你需要什麼看到? – Deepak 2011-05-29 13:00:26

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。在您的查詢中,如果您想進行範圍比較,則需要直接使用時間戳。時間戳已經包含您需要做這個比較的所有數據。您不需要將其轉換爲日/月/年來比較它。

你需要做的是這樣的:

找到所有值,其中我timestampcreate a new date from '13/05/11'create a new date from '30/05/11'之間。 pt.timestamp已經是一個時間戳,不需要在你的WHERE子句中進行轉換。

你一直在做的是把它轉換成字符串表示。這就好,當你想顯示它,但不是當你想比較它與其他值。

+0

我不得不將DATE_FORMAT()應用於時間戳? – Deepak 2011-05-29 12:44:33

+1

'TO_DATE'函數在MySQL中不存在,但有一個'STR_TO_DATE'函數:http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_str到目前爲止@Deepak'DATE_FORMAT'返回一個字符串,我認爲這是問題,請參閱我的答案。 – krtek 2011-05-29 12:45:27

+0

我用過,但檢查我的編輯.. – Deepak 2011-05-29 12:59:54