当唯一 id 与查询的其他 7 个不匹配时,如何从 MySQL 查询中绘制一行
Posted
技术标签:
【中文标题】当唯一 id 与查询的其他 7 个不匹配时,如何从 MySQL 查询中绘制一行【英文标题】:How to draw one row from a MySQL query when the unique id doesn't match 7 others queried 【发布时间】:2020-04-25 09:36:28 【问题描述】:我有一个新闻故事数据库,我有一个阅读量最大的部分。我的新闻以 8 个故事的块显示。前 7 个来自下面的 mysql 查询,显示过去 7 天 (DESC) 中阅读最多的前 7 个故事。这正如我所期望的那样工作,并显示前 7 个阅读最多的新闻故事。
$query = "
SELECT *
FROM news
WHERE STR_TO_DATE(day, '%d %M %Y') >= DATE_SUB(curdate(), INTERVAL 1 WEEK)
ORDER
BY mostRead DESC
LIMIT 7
";
$results = mysqli_query($dbc, $query)or die('Error querying database');
while ($rows = mysqli_fetch_array($results))
echo news stories
我正在努力研究如何形成下一个 MySQL 查询。我需要显示的第 8 个新闻故事必须是我的数据库中第一个不在阅读最多的前 7 个新闻故事中的故事。这是为了避免 8 层楼的重复。
例如,如果一个新的新闻报道有大量的点击量,我不希望它出现在前 7 名,然后也作为第 8 条新闻报道,因为它仍然是最新条目。
【问题讨论】:
请注意,函数不能使用索引,所以如果你能想办法去除它们,性能将得到不可估量的提升 @StevenLafferty 。 . .我很困惑。为什么不直接将“7”改为“8”来获取 8 条头条新闻? 【参考方案1】:如果您运行的是 MySQL 8.0,则可以使用 row_number()
或 rank()
:
order by
case when rank() over(order by mostRead desc) <= 7,
then mostRead
else 0
end desc,
str_to_date(day, '%d %M %Y') desc
limit 8
如果当前行排在前 7 位,则第一个排序条件中的条件表达式返回 mostRead
,否则返回 0
(因此所有其他行都是并列的)。然后,第二个排序条件使用日期。剩下要做的就是将结果集限制为 8 行。
【讨论】:
我的 MySQL 非常有限,我使用 phpMyAdmin,由我的服务提供商提供,从我可以在数据库服务器下收集到的版本:服务器版本:5.7.23-23 - Percona Server (GPL ),第 23 版,修订版 500fcf5。甚至不接近 MySQL 8.0!这是否意味着上述建议的功能将无法运行?【参考方案2】:您可以使用UNION 向结果集中添加额外的行。这些查询将适用于较旧的 MySQL 版本(在 5.7.26 上测试)。
实现这一点的方法很少,您可以从表中添加前 8 行,让 UNION
过滤重复项,然后通过在查询末尾添加 LIMIT 8
只选择一条记录:
(SELECT *
FROM news
WHERE STR_TO_DATE(day, '%d %M %Y') >= DATE_SUB(curdate(), INTERVAL 1 WEEK)
ORDER BY mostRead DESC
LIMIT 7)
UNION
(SELECT *
FROM news
ORDER BY str_to_date(day, '%d %M %Y') DESC
LIMIT 8)
LIMIT 8
或者您可以自己过滤更适合高级用例的行。
(SELECT *
FROM news
WHERE STR_TO_DATE(DAY, '%d %M %Y') >= DATE_SUB(curdate(), INTERVAL 1 WEEK)
ORDER BY mostRead DESC
LIMIT 7)
UNION
(SELECT *
FROM news
WHERE id NOT IN
(SELECT id
FROM
(SELECT *
FROM news
WHERE STR_TO_DATE(day, '%d %M %Y') >= DATE_SUB(curdate(), INTERVAL 1 WEEK)
ORDER BY mostRead DESC
LIMIT 7) temp)
ORDER BY str_to_date(day, '%d %M %Y') DESC
LIMIT 1)
我们添加了temp
表,因为旧版本的 MySQL 不支持 LIMIT & IN/ALL/ANY/SOME 子查询。
【讨论】:
谢谢大家的回答。正如我所说,我不是专家,但我会解决这些问题,现在让你知道我的进展情况。非常感谢cmets,谢谢【参考方案3】:我需要显示的第 8 个新闻故事必须是我的数据库中第一个不在阅读次数最多的前 7 个新闻故事中的故事。
这是你想要的吗?
SELECT n.*
FROM news n
WHERE STR_TO_DATE(day, '%d %M %Y') >= DATE_SUB(curdate(), INTERVAL 1 WEEK)
ORDER BY mostRead DESC
LIMIT 8
------^ this is the change
如果您的应用程序中已经有 7 并且需要获得不同的,那么您需要处理 id:
SELECT n.*
FROM news n
WHERE STR_TO_DATE(day, '%d %M %Y') >= DATE_SUB(curdate(), INTERVAL 1 WEEK) AND
n.id NOT IN ($id1, $id2, $id3, $id4, $id5, $id6, $id7)
ORDER BY mostRead DESC
LIMIT 1
【讨论】:
以上是关于当唯一 id 与查询的其他 7 个不匹配时,如何从 MySQL 查询中绘制一行的主要内容,如果未能解决你的问题,请参考以下文章
使用 Mongoose 从 JSON 对象数组中查询具有匹配 ID 的集合
Mongoose find - 从查询中返回所有匹配的至少一个
在 R 中,当 ID 不唯一时,如何从每个 ID 的数据框中获取倒数第二行? [复制]