我的问题(也许)有点复杂,我试着写下来可以理解。 我有一个PHP类,它根据几种情况和参数生成MySQL查询(然后在dinamyc表中显示查询结果)。 例如,这里有表格和示例查询:
很简单,有用户,每个用户可以分配一个或多个配置文件。 例如,我们只有一个用户,他有两个配置文件:
[USER]
userid login password status reg_date
------ ------- ---------- ------ -------------------
1 JohnDoe hd98349... 0 2014-01-09 16:00:55
[PROFILE]
profile_id profile_name
---------- ------------
1 admin
2 root
3 user
[USER_PROFILE]
relation_id user profile
----------- ----- -------
1 1 1
2 1 2
我的PHP代码生成一个如下所示的查询:
SELECT
userid AS 'User id',
login AS 'User name',
GROUP_CONCAT(profile_name SEPARATOR ', ') AS 'Profile(s)',
`status`
FROM `user` LEFT JOIN user_profile ON `user`.userid = user_profile.`user`
LEFT JOIN `profile` ON user_profile.`profile` = `profile`.profile_id
WHERE
status IN (0, 1)
ORDER BY reg_date ASC
LIMIT 0 ,10
此查询的结果是:
[RESULT]
User id User name Profile(s) status
------- --------- ---------- ------
1 JohnDoe root, admin 0
当我想在源自子查询或复杂表达式的列(例如GROUP_CONCAT(profile_name SEPARATOR ', ')
)上使用过滤器时,我得到错误的结果:
SELECT COUNT(*) AS 'all_rows'
FROM `user` LEFT JOIN user_profile ON `user`.userid = user_profile.`user`
LEFT JOIN `profile` ON user_profile.`profile` = `profile`.profile_id WHERE status IN (0, 1)
HAVING GROUP_CONCAT(profile_name SEPARATOR ', ') LIKE '%root%'
这将导致:' all_rows' => 2。 这是因为HAVING中的GROUP_CONCAT赢了组,但是如果我把它放在SELECT中就像:SELECT COUNT(GROUP_CONCAT(profile_name SEPARATOR','))我得到一个错误
所以问题是如何在过滤器(WHERE / HAVING)表达式中使用GROUP_CONCAT获取所有行的数量?
编辑:在运行主查询之前,我需要知道它会产生多少记录行,而不受LIMIT限制。我使用它来计算LIMIT的起始行值以进行分页。
答案 0 :(得分:0)
SELECT `user`.userid,
GROUP_CONCAT(profile_name SEPARATOR ', ') as roles,
COUNT(*) AS 'all_rows'
FROM `user`
LEFT JOIN user_profile ON `user`.userid = user_profile.`user`
LEFT JOIN `profile` ON user_profile.`profile` = `profile`.profile_id
WHERE status IN (0, 1)
GROUP BY `user`.userid
HAVING GROUP_CONCAT(profile_name SEPARATOR ', ') LIKE '%root%'
答案 1 :(得分:0)
您有一个不寻常的查询,其中计数将返回0或1.您可以通过使用子查询来解决此问题:
SELECT COUNT(*) AS 'all_rows'
FROM (SELECT GROUP_CONCAT(profile_name SEPARATOR ', ') as pns
FROM `user` LEFT JOIN
user_profile
ON `user`.userid = user_profile.`user` LEFT JOIN
`profile`
ON user_profile.`profile` = `profile`.profile_id
WHERE status IN (0, 1)
) t
WHERE pns LIKE '%root%';
您还可以通过将逻辑移至where
子句来解决问题:
SELECT COUNT(*)
FROM `user` LEFT JOIN
user_profile
ON `user`.userid = user_profile.`user` LEFT JOIN
`profile`
ON user_profile.`profile` = `profile`.profile_id
WHERE status IN (0, 1) and profile_name like '%root%';
答案 2 :(得分:0)
我喜欢解决方案: 这是记录计数查询的外观:
SELECT COUNT(*) AS 'all_rows'
FROM (SELECT
userid AS 'User id',
login AS 'User name',
GROUP_CONCAT(profile_name SEPARATOR ', ') AS 'Profile(s)',
status
FROM `user` LEFT JOIN user_profile ON `user`.userid = user_profile.`user`
LEFT JOIN `profile` ON user_profile.`profile` = `profile`.profile_id
HAVING
status IN (0, 1)
AND GROUP_CONCAT(profile_name SEPARATOR ', ') LIKE '%root%') t
这是主要问题:
SELECT
userid AS 'User id',
login AS 'User name',
GROUP_CONCAT(profile_name SEPARATOR ', ') AS 'Profil(ok)',
status
FROM `user` LEFT JOIN user_profile ON `user`.userid = user_profile.`user`
LEFT JOIN `profile` ON user_profile.`profile` = `profile`.profile_id
HAVING
status IN (0, 1)
AND GROUP_CONCAT(profile_name SEPARATOR ', ') LIKE '%root%'
ORDER BY reg_date ASC
LIMIT 0 ,10
我必须在任何地方使用HAVING
而不是WHERE
,因为我说主要查询是以编程方式生成的。这是我在SELECT部分中设置列的方法:
$listObj->setColumns(array('userid' => 'User id',
'login' => 'User name',
'GROUP_CONCAT(profile_name SEPARATOR \', \')' => 'Profile(s)'));
当用户在引用GROUP_CONCAT(profile_name SEPARATOR ', ') AS 'Profile(s)'
列的过滤器输入中键入%root%表达式时,我无法确定GROUP_CONCAT(profile_name SEPARATOR ', ') LIKE %root%
部分是WHERE
部分还是HAVING
因为它与任何其他列一起处理(比如
userid AS 'User id'
或login AS 'User name'
列)
剩下的技术问题是在任何地方使用HAVING
都是错误的,即使简单的WHERE
就足够了吗?