子查询中的Mysql LIMIT

问题描述 投票:0回答:3

我有这个 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(在内部语句中)

如果有人能给我一些代码我将非常感激

谢谢

mysql
3个回答
8
投票

这个怎么样:

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
  }

0
投票

我不知道这是不是你想要的,这个问题有点混乱。我不明白为什么你对同一个表使用子查询。无论如何,LIMIT 与 MSSQL 的“TOP”相同,因此 LIMIT 2 应该只返回两条记录。

如果这不是您想要的,请发表评论,我将编辑我的答案:

SELECT  id
FROM    articles
WHERE  section=1 AND is_top_story != 1
ORDER BY timestamp DESC 

0
投票

现在 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;

我认为这个解决方案对于这种特殊情况没有多大意义(它也更冗长)。只是提及解决方法,以防有人发现它有用。

© www.soinside.com 2019 - 2024. All rights reserved.