2016-10-12 38 views
-1

我目前在做後續的過去6個月,但它似乎是它可以做更好的方式(較少的代碼行,可能更優化)MySQL查詢能不能做到更好

$monthones = mktime(0, 0, 0, date("n") - 1, 1); 
$monthonef = mktime(0, 0, 0-1, date("n"), 1); 

$query = "SELECT COUNT(*) FROM users WHERE type = '1' AND status = '1' AND (date >= '".$monthones."' AND date <= '".$monthonef."');"; 
$result = $pdo->query($query); 
$monthone = $result->fetchColumn(); 

$query = "SELECT COUNT(*) FROM users WHERE type = '3' AND status = '1' AND (date >= '".$monthones."' AND date <= '".$monthonef."');"; 
$result = $pdo->query($query); 
$monthone2 = $result->fetchColumn(); 

$monthtwos = mktime(0, 0, 0, date("n") - 2, 1); 
$monthtwof = mktime(0, 0, 0-1, date("n") - 1, 1); 

$query = "SELECT COUNT(*) FROM users WHERE type = '1' AND status = '1' AND (date >= '".$monthtwos."' AND date <= '".$monthtwof."');"; 
$result = $pdo->query($query); 
$monthtwo = $result->fetchColumn(); 

$query = "SELECT COUNT(*) FROM users WHERE type = '3' AND status = '1' AND (date >= '".$monthtwos."' AND date <= '".$monthtwof."');"; 
$result = $pdo->query($query); 
$monthtwo2 = $result->fetchColumn(); 

我還有4個月的休息時間。任何建議如何我可以改善這一點?我正在考慮結合查詢並在循環結果時開始計數?或者會更糟?

+4

可能屬於上codereview.stackexchange.com – Kritner

+1

見**第2節/是什麼顯示您的Schema Mean?** [什麼是Sqlfiddle,爲什麼要關注?](http://stackoverflow.com/a/38899465)幫助我們幫助您:p – Drew

回答

0

似乎運行一個對數據庫的查詢會更有效率,一次通過數據。

對於日期範圍的條件下,而不是減去第二,使用

<= last second of month 

我更喜歡使用使用

< first second of following month 

圖案如果在原始代碼中的邏輯爲正確生成「開始」和「結束」邊界,我們只需要7個邊界值,每月的第一秒:

$month00 = mktime(0, 0, 0, date("n") - 0, 1); 
$month01 = mktime(0, 0, 0, date("n") - 1, 1); 
$month02 = mktime(0, 0, 0, date("n") - 2, 1); 
$month03 = mktime(0, 0, 0, date("n") - 3, 1); 
$month04 = mktime(0, 0, 0, date("n") - 4, 1); 
$month05 = mktime(0, 0, 0, date("n") - 5, 1); 
$month06 = mktime(0, 0, 0, date("n") - 6, 1); 

然後查詢可以是這樣的:

$query = " 
SELECT SUM(u.type = '1' AND u.date >= '$month01' AND u.date < '$month00') AS monthone 
    , SUM(u.type = '3' AND u.date >= '$month01' AND u.date < '$month00') AS monthone2 

    , SUM(u.type = '1' AND u.date >= '$month02' AND u.date < '$month01') AS monthtwo 
    , SUM(u.type = '3' AND u.date >= '$month02' AND u.date < '$month01') AS monthtwo2 

    , ... 
    , ... 

    , SUM(u.type = '1' AND u.date >= '$month06' AND u.date < '$month05') AS monthsix 
    , SUM(u.type = '3' AND u.date >= '$month06' AND u.date < '$month05') AS monthsix2 

    FROM users u 
WHERE u.status = '1' 
    AND u.type IN ('1','3') 
    AND u.date >= '$month06' 
    AND u.date < '$month00' 
"; 

...將通過重複表達模式返回列monththree/monththree2更換,monthfour/monthfour2monthfive/monthfive2

注意,這使用MySQL簡寫,SUM()聚合內的表達式評估爲1(如果條件爲TRUE)或0(如果條件爲FALSE)或NULL。

我們必須抓取整行來獲取所有計數。我們不得不消除fetchColumn()並改用fetch()

$result = $pdo->query($query); 
$row = $result->fetch(PDO::FETCH_ASSOC); 

如果我們需要在標變量的值,所以我們不必更改後續代碼:

$monthone = $row['monthone']; 
$monthone2 = $row['monthone2']; 
$monthtwo = $row['monthtwo']; 
$monthtwo2 = $row['monthtwo2']; 
... 
... 
$monthsix = $row['monthsix']; 
$monthsix2 = $row['monthsix2']; 
+0

魔獸真棒回覆就像一個魅力!只是一個簡單的問題,如果你不介意。如果我只有2個查詢運行(例如只有一個月),那麼執行上述解決方案還是使用fetchColumn運行2個查詢會更好?謝謝! –

+0

我寧願運行一個查詢來獲得一個月的兩個計數。一個穿過表格中的行。讓數據庫完成這項工作。對於非平凡集合,表格應該有適當的索引(我們的查詢可以有效地使用)。 – spencer7593

+0

作爲原始模式和這個模式之間的折中,我至少會得到一個月的兩個計數查詢。這將運行六個查詢,而不是十二個(與原來的相比)。 – spencer7593

0

你可以返回所有的計數使用conditional aggregation一個查詢:

select count(case when type = '1' AND 
        date >= '".$monthones."' AND date <= '".$monthonef."' then 1 end) cnt1, 
     count(case when type = '3' AND 
        date >= '".$monthones."' AND date <= '".$monthonef."' then 1 end) cnt2, 
     count(case when type = '1' AND 
        date >= '".$monthtwos."' AND date <= '".$monthtwof."' then 1 end) cnt3, 
     count(case when type = '3' AND 
        date >= '".$monthtwos."' AND date <= '".$monthtwof."' then 1 end) cnt4 
from users 
where status = '1' 
+0

...'並輸入(' 1','3')和日期> ='$ monthsixs'和日期<'$ monthzeros'' – spencer7593

+0

嗯,它似乎並沒有工作。我沒有得到相同的結果。 –

+0

也許這是fetchColumn問題? –

0

你可以只使用一個SQL查詢解決。 請試試這個:

select count(case when type= '1' then 1 end) type_one 
    , count(case when type= '3' then 1 end) type_three 
    , DATE_FORMAT(FROM_UNIXTIME(date),'%Y-%m') month 
from users 
where status = '1' 
    and date between UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -6 MONTH)) and UNIX_TIMESTAMP(CURDATE()) 
group by DATE_FORMAT(FROM_UNIXTIME(date),'%Y-%m') 

您可以用參數替換CURDATE()。

+0

根據問題中的查詢,它看起來像'date'列可能被定義爲* integer *數據類型,而不是MySQL DATE,DATETIME或TIMESTAMP數據類型。 – spencer7593