MySQL查询可以做得更好

时间:2016-10-12 18:10:04

标签: php mysql sql pdo

我目前正在进行过去6个月的跟进,但似乎可以做得更好(更少的代码行,可能更优化)

$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个月的休息时间。有什么建议我可以改进吗?我在考虑组合查询并在循环结果时开始计数?或者会更糟糕?

3 个答案:

答案 0 :(得分: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'

答案 1 :(得分: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()。

答案 2 :(得分:0)

似乎对数据库运行一个查询会更有效,一个传递数据。

对于日期范围条件,而不是减去秒,并使用

<= last second of month

我更喜欢使用

模式
<  first second of following month

如果原始代码中的逻辑对于生成&#34; start&#34;并且&#34;完成&#34;边界,我们只需要七个边界值,即每个月的第一个:

$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 / monththree2monthfour / 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'];