2016-10-12 40 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