mySQL 查询返回根据'LIMIT' 使用而改变 |数据库
Posted
技术标签:
【中文标题】mySQL 查询返回根据\'LIMIT\' 使用而改变 |数据库【英文标题】:mySQL query return changing based on 'LIMIT' useage | DatabasemySQL 查询返回根据'LIMIT' 使用而改变 |数据库 【发布时间】:2021-11-01 00:56:45 【问题描述】:我的网站有一个使用 php 和 mysql 数据库来存储和提取数据的消息传递系统。
我有一个 _CONVERSATION 表和一个 _MESSAGE 表。前者存储有关与对话关联的收件箱数据的信息。后者比前者弱,并存储包括消息发送日期在内的单个消息数据。当用户加载消息页面时,我希望按用户最近的对话顺序加载收件箱。为此,我创建了一个查询,该查询从 _MESSAGE 表中选择不同的 convoID,该表按 messageID 排序(在按消息日期排序时也可以正常工作,也会出现同样的问题)。
当用户加载消息页面时,我使用所讨论的查询来提取用户参与的最后 10 个对话。我对此使用了限制,并使用 PDO while-fetch 将数据加载到数组中。
这按预期发生,没有问题。
有限制的 PDO SQL:
'SELECT distinct convoID from _MESSAGE where receiverID = :userID or senderID = :userID order by messageID desc limit '.(int)$ext[0].';'
/// userID = 40 (same every time for testing)
/// $ext[0] = 10
/// RESULT: 171, 8, 194, 193, 187, 178, 173, 157, 12, 151 (EXPECTED)
当用户在收件箱中向下滚动时,网站会加载前十个之外的更多对话。我没有限制地运行相同的查询。我运行 while-fetch 直到找到最后一个加载的用户,然后我将接下来的五个项目加载到返回的数组中。一旦加载了五个新项目,我就会跳出 PHP while 循环。
这是我注意到一些奇怪行为的地方。我没有得到预期的结果,并且正在重复一些 convoID。我设置了一个echo $row['convoID'].', ';
来获取完整的查询。
无限制的 PDO SQL:
'SELECT distinct convoID from _MESSAGE where receiverID = :userID or senderID = :userID order by messageID desc;'
/// userID = 40 (same every time for testing)
/// Set up to echo five items after last convoID is found
/// RESULT: 194, 193, 187, 178, 173, 171, 157, 151, 136, 13, 3, 6, 8, 10 (UNEXPECTED)
来自 mySQL 工作台的 SQL:
select distinct convoID from _MESSAGE where receiverID = 40 or senderID = 40 order by messageID desc;
# RETURNS: 171,8,194,193,187,178,173,157,12,151,etc (EXPECTED)
这是我想要并期望从这个查询中得到的回报。
这不是 PDO 第一次按照我的预期启动。我想知道是什么导致了这种奇怪的行为,以及如何在不使用限制的情况下从 PDO 查询中获得预期结果。
我在查询中写错了吗?如果是这样,为什么在 mySQL 工作台中运行相同的精确查询时没有问题?
这里是完整的php函数供参考:
function get_convos($conn, $userID, $ext = ['10',''])
/// EXT: ['How many to pull','pull all convos after']
$_rtn = [];
$l = 0;
$sql = null;
if ($ext[1] == '')
$sql = $conn->prepare('SELECT distinct convoID from _MESSAGE where receiverID = :userID or senderID = :userID order by messageID desc limit '.(int)$ext[0].';');
$sql->execute(['userID' => $userID]);
else
$sql = $conn->prepare('SELECT distinct convoID from _MESSAGE where receiverID = :userID or senderID = :userID order by messageID desc;');
$sql->execute(['userID' => $userID]);
$ready = false;
while ($row = $sql->fetch(PDO::FETCH_ASSOC))
echo $row['convoID'].', ';
$sql2 = $conn->prepare('SELECT * from _CONVERSATION where convoID = :convoID;');
$sql2->execute(['convoID' => $row['convoID']]);
if ($row2 = $sql2->fetch(PDO::FETCH_ASSOC))
if ($ext[1] == '')
$_rtn[$l] = $row2;
$l++;
else
if ($ready)
if ($l < (int)$ext[0])
$_rtn[$l] = $row2;
$l++;
else
break;
if ($row2['convoID'] == $ext[1])
$ready = true;
return $_rtn;
感谢你们提供的任何帮助。
【问题讨论】:
【参考方案1】:问题是ORDER BY messageID
被处理之后它从每个convoID
组中选择一个不同的消息,并且它选择哪一行是不可预测的。 MySQL 根据是否存在LIMIT
子句对查询的处理方式不同,因此您会得到不同的结果。
您需要使用确定性方法在每个对话中选择要排序的消息,例如按最新消息排序。见SQL select only rows with max value on a column
【讨论】:
谢谢!这就是最终的工作:SELECT convoID from _MESSAGE where receiverID = :userID or senderID = :userID group by convoID order by max(date) desc;
以上是关于mySQL 查询返回根据'LIMIT' 使用而改变 |数据库的主要内容,如果未能解决你的问题,请参考以下文章