我有这个 mysql 语句,但我在子查询错误中收到 LIMIT
SELECT id
FROM articles
WHERE section=1 AND id NOT IN
(
SELECT id
FROM articles
WHERE is_top_story=1 ORDER BY timestamp DESC LIMIT 2
)
我想从表中选择所有 id-s,其中section=1 且 id-s 不在我的内部(第二)语句中
+--id--+section+-is_top_story-+--timestamp--+
| 54 | 1 | 1 | 130 |
| 70 | 2 | 0 | 129 |
| 98 | 3 | 1 | 128 |
| 14 | 1 | 1 | 127 |
| 58 | 4 | 0 | 126 |
| 13 | 3 | 1 | 125 |
| 64 | 1 | 1 | 124 |
| 33 | 1 | 1 | 123 |
我的sql应该返回64和33(它们与section=1和is_top_story=1),因为54和14(在内部语句中)
如果有人能给我一些代码我将非常感激
谢谢
这个怎么样:
SELECT a.id, a.times
FROM articles AS a
LEFT JOIN (
SELECT id
FROM articles
WHERE is_top_story =1
ORDER BY times DESC LIMIT 2) AS ax
USING (id)
WHERE section = 1 AND ax.id IS NULL;
当您需要子查询限制时,Join 是一种常见的解决方法;需要排除逻辑只需将这些“左连接 - join.id IS NULL”部分添加到查询中。 )
更新:你的例子有点困惑。您引用的原始查询是“获取一些section = 1的文章,然后取出属于最近2个top_stories的文章”。但在您的示例中,在选择这些要忽略的故事时也应考虑该部分...
实际上,用该条件更新我的查询也很容易:只需替换
WHERE is_top_story = 1
与
WHERE is_top_story = 1 AND section = 1
...但我认为在客户端代码中可能会更好地解决这个问题。首先,您发送一个简单的查询,没有任何连接:
SELECT id, is_top_story
FROM articles
WHERE section = 1
ORDER BY times DESC;
然后您只需遍历获取的行集,并忽略带有“is_top_story”标志的前两个元素,如下所示:
...
$topStoriesToIgnore = 2;
foreach ($rowset as $row) {
if ($row->is_top_story && $topStoriesToIgnore-- > 0) {
continue;
}
// actual processing code goes here
}
我不知道这是不是你想要的,这个问题有点混乱。我不明白为什么你对同一个表使用子查询。无论如何,LIMIT 与 MSSQL 的“TOP”相同,因此 LIMIT 2 应该只返回两条记录。
如果这不是您想要的,请发表评论,我将编辑我的答案:
SELECT id
FROM articles
WHERE section=1 AND is_top_story != 1
ORDER BY timestamp DESC
现在 MySQL 支持
ROW_NUMBER()
,另一个选项可以是生成“索引列”,然后在 WHERE 子句中引用它。这个解决方案还意味着使用 JOIN,所以我在 raina77ow 的基础上编写我的答案。
SELECT a.id, a.times
FROM articles AS a
LEFT JOIN (
SELECT id, ROW_NUMBER() OVER (ORDER BY times DESC) AS index
FROM articles
WHERE is_top_story = 1) AS ax
USING (id)
WHERE section = 1 AND ax.id IS NULL AND ax.index <= 2;
我认为这个解决方案对于这种特殊情况没有多大意义(它也更冗长)。只是提及解决方法,以防有人发现它有用。