我运营的网站用户数量很少,我希望很快就会增长。我正在使用共享的Web托管服务,我无法在Web服务器上更改MySQL默认设置。我正在尝试最小化查询并找到一个重复的查询对(通过setTimeout到Ajax调用每10秒发生一次),其中GROUP_CONCAT可以帮助减少以下2个查询:
$logid = mysqli_real_escape_string($cxn, $_SESSION['login_id']);
$sql1 = mysqli_query($cxn, "SELECT COUNT(bid) AS count FROM table1 WHERE login_id = '$logid'");
$sql2 = mysqli_query($cxn, "SELECT cid FROM table2 WHERE (login_id1 = '$logid' OR login_id2 = '$login_id')");
一个查询:
SELECT COUNT(table1.bid) AS count,
GROUP_CONCAT(table2.cid) AS cidList
FROM table1
LEFT JOIN table2
ON (table1.login_id = table2.login_id1 OR table1.login_id = table2.login_id2)
WHERE table1.login_id = '$logid';
问题是group_concat_max_len
默认设置为1024,我调用了我的共享托管服务,我无法更改它。上面查询中的每个table2.cid都是20个字符,所以(包括逗号分隔符)GROUP_CONCAT只能返回48个table2.cid记录,但我需要能够返回多达1000个。我已经知道我可以更改这个使用如下查询的默认限制:
SET SESSION group_concat_max_len = 1000000;
但是这个添加的查询失败了,因为即使上面的两个查询被压缩到一个查询,我现在已经添加了这个最新的查询,所以每次进行Ajax调用两个查询都是仍然做了(我还没有保存任何东西)。
是否有某种方法可以将GROUP_CONCAT聚集在一起,为每个GROUP_CONCAT检索一些记录(table2.cid)?例如,类似于(例如100条记录):
SELECT COUNT(table1.bid) AS count,
GROUP_CONCAT(table2.cid ORDER BY table2.cid LIMIT 0,47) AS cidList1,
GROUP_CONCAT(table2.cid ORDER BY table2.cid LIMIT 48,95) AS cidList2,
GROUP_CONCAT(table2.cid ORDER BY table2.cid LIMIT 96,99) AS cidList3
FROM table1
LEFT JOIN table2
ON (table1.login_id = table2.login_id1 OR table1.login_id = table2.login_id2)
WHERE table1.login_id = '$logid';
顺便说一下,我尝试了一个测试用例并且查询因添加LIMIT而失败,因为没有LIMIT会返回正确的PHP回显字符串,并且使用LIMIT返回一个空的PHP回显字符串以及错误日志消息:
PHP Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given in
答案 0 :(得分:3)
只需发出常规SELECT table1.bid, table2.cid FROM ...
即可。如果bid
永远不是NULL
,那么SELECT cid
就足够了(在这种情况下,COUNT(bid) = COUNT(cid)
)
计算bid
并加入应用层中的cid
列表几乎是即时的。无论如何,以逗号分隔的cid
列表的构建绝对属于此层。
至于bid
的计数,这不太明显。如果你真的想让MySQL做计数并仍然保存一个数据库调用,我宁愿做这样的事情:
SELECT COUNT(table1.bid) FROM table1 WHERE blah blah
UNION ALL
SELECT cid FROM table2 WHERE blah blah
但这是理论。说真的,不要这样做。
第二个想法,实际上有一个不那么尴尬的解决方案:
SELECT COUNT(table1.bid), table2.cid FROM ...
GROUP BY table2.cid WITH ROLLUP
table2.cid
为NULL
的最后一行包含总计数。
答案 1 :(得分:2)
这是给你的一招:
SELECT COUNT(table1.bid) AS count,
GROUP_CONCAT(case when mod(table2.cid,3)=0 then table2.cid else null end) AS cidList1,
GROUP_CONCAT(case when mod(table2.cid,3)=1 then table2.cid else null end) AS cidList2,
GROUP_CONCAT(case when mod(table2.cid,3)=2 then table2.cid else null end) AS cidList3
FROM table1
LEFT JOIN table2
ON (table1.login_id = table2.login_id1 OR table1.login_id = table2.login_id2)
WHERE table1.login_id = '$logid';