好还是坏? - PHP循环中的Doctrine DBAL查询

时间:2014-11-05 16:22:31

标签: php mysql doctrine-orm

我可能需要一些建议。

任务是从MySQL-Database-Table生成一些统计信息。我使用Doctrine DBAL Class进行查询。

所以我们这里有两个表(例如缩小):

USERS-表

user_id | user_name  | user_gender | ...
---------------------------------------
1234    | Klark Kent | 1           | ...
2468    | Lex Luthor | 1           | ...
3579    | Louis Lane | 2           | ...
....


签入-表

checkin_id | checkin_user_id | checkin_month | ...
--------------------------------------------------
1          | 1234            | 1             | ...
2          | 2468            | 1             | ...
3          | 1234            | 1             | ...
4          | 1234            | 2             | ...
....


统计结果最终应该是这样的:

Month | All | Male | Female | Unique
------------------------------------
Jan   | 312 | 179  | 133    | 224
Feb   | 295 | 169  | 135    | 218
Mar   | 301 | 154  | 147    | 230
....


所以基本上我是这样做的:

for ($i = 1; $i <= 12; $i++) {    
  $QB = $DB->createQueryBuilder();  
  $STMT = $QB
      ->select('c.checkin_id')
      ->from(CHECKIN_TABLE, 'c')
      ->innerJoin('c', USER_TABLE, 'u', 'c.checkin_user_id = u.user_id')
      ->where('u.user_gender = 1')
      ->andWhere('c.checkin_month = :month')
      ->setParameter('month', (int)$i)
      ->execute();
  ;
  $stats[$i]['male'] = $STMT->rowCount();
  $QB = $DB->createQueryBuilder();  
  $STMT = $QB
      ->select('c.checkin_id')
      ->from(CHECKIN_TABLE, 'c')
      ->innerJoin('c', USER_TABLE, 'u', 'c.checkin_user_id = u.user_id')
      ->where('u.user_gender = 2')
      ->andWhere('c.checkin_month = :month')
      ->setParameter('month', (int)$i)
      ->execute();
  ;
  $stats[$i]['female'] = $STMT->rowCount();
  $stats[$i]['all'] = $stats[$i]['male']+$stats[$i]['female'];
  $QB = $DB->createQueryBuilder();  
  $STMT = $QB
      ->select('DISTINCT checkin_user_id')
      ->from(CHECKIN_TABLE, 'c')
      ->where('checkin_month = :month')
      ->setParameter('month', (int)$i)
      ->execute();
  ;
  $stats[$i]['unique'] = $STMT->rowCount();
}

正如您所看到的,我在12次循环中运行3次查询。由于查询相对简单,这可能没问题,但如果可以做得更好,我会很高兴听到您的意见吗?

可能选择所有条目,然后使用大量IF子句进行WHILE-Fetch循环?

if ( ($row['checkin_month'] == 1) && ( $row['user_gender'] == 1 ) $stats[1]['male']++;
if ( ($row['checkin_month'] == 1) && ( $row['user_gender'] == 2 ) $stats[1]['female']++;
if ( ($row['checkin_month'] == 2) && ( $row['user_gender'] == 1 ) $stats[2]['male']++;
if ( ($row['checkin_month'] == 2) && ( $row['user_gender'] == 2 ) $stats[2]['female']++;


正如我们在这里,还有一个问题。我已经读过使用DISTINCT来删除重复的条目并不是最好的做法,但是我不知道我怎么能这样做。我已经读过有关WHERE EXISTS的内容,但是这不起作用,因为我只是在这里查询DISTINCT调用的单个表,我认为。

如果您有任何提示或想法,请告诉我。 谢谢大家。

1 个答案:

答案 0 :(得分:0)

幸运的是,在阅读和搜索了很多东西后,我自己找到了解决方案。

因此对于可能有类似任务的每个人来说,这是如何通过单个查询完成的 (但我不知道如何使用Query-Builder构建它,但它可以用作SQL语句。)

$SQL = 'SELECT
         c.checkin_month, count(*) AS count,
         count(DISTINCT c.checkin_member_id) AS uniq,
         sum(case when u.user_gender = 1 then 1 else 0 end) AS male,
         sum(case when u.user_gender = 2 then 1 else 0 end) AS female
        FROM 
         '.CHECKIN_TABLE.' c,
         '.USER_TABLE.' u
        WHERE
         c.checkin_user_id = u.user_id
        GROUP BY
         c.checkin_month';
$res = $DB->fetchAll($SQL);


因此代码更少,查询更少,结果相同。