【问题标题】:Select N rows before and after given row with condition在给定行之前和之后选择 N 行有条件
【发布时间】:2012-05-22 22:14:34
【问题描述】:
id  title   cat lang
6101    AAba    1   1
6102    AAad    4   2
6103    AAaf    4   2
6104    AAa 1   1
6105    AAtar   4   2
6106    AAao    1   1
6107    ABya    4   2
6108    ABar    4   2
6109    ACar    1   2
6110    BCad    3   1
6111    CCas    4   1
6112    DCas    4   2
6113    GCaz    2   2
6114    FCaew   2   2
6115    FCaw3   4   2
6116    FCa3    1   1
6117    FCa4    4   2
6118    FCa5    2   1
6119    FCa6    4   2 --- last id

表格新闻,id是主键,title-是title字段, cat - 有四种类型的新闻类别,lang - 语言代码 1 或 2。

我想实现以下目标: 1) 案例编辑新闻 - id 可用 - 例如 6111,lang 为 1,cat 为 4 我想收集这些id和title:

6119
6117
6115
6112
6109
6105
6103
6102

它们是相反的语言 - lang 是 2,同一类别 cat 是 4 和 在给定 id 6111 之前和之后的 4(或 n)个 id 范围内 还订购了描述

2) 案例添加新闻 - id 不可用,或者在 php 中插入后是 mysql_insert_id() 相同的功能 - 最后 10 个 id 具有相同的 cat = 4 和相反的 lang = 2

到目前为止,我已经尝试过:

对于案例 1) php sn-p:

   $id = 6111;
    $lang = 1;
    $tip = 4;
    $sql = "SELECT id, title 
            FROM pubs 
            WHERE id BETWEEN ".($id-4)." AND ".($id+4). " AND 
            tip = ".$tip." AND 
            lang <> ".$lang." 
            ORDER BY id DESC ";

但是这会在 id 之前和之后获得 4 个 id,而不是来自我需要的 id 集合。

对于案例 2)

$sql = "SELECT id, title 
        FROM news 
        WHERE cat = 4 AND 
        lang <> 1 
        ORDER BY id DESC LIMIT 10";

这似乎有效,但可能是我错了。

有没有办法用php和mysql来实现案例1? 案例 2 的更好方法?

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    鉴于你只有$id,这个看起来很可怕的野兽是我能想到的最好的。我相当确定有一种更整洁的方法可以做到这一点,但我认为这会起作用(FIXED)

    $id = 6111;
    
    $query = "
      SELECT `id`, `title`
      FROM `news`
      WHERE `id` IN (
        SELECT * FROM (
          SELECT `id`
          FROM `news`
          WHERE `cat` = (
            SELECT `cat`
            FROM `news`
            WHERE `id` = ".$id."
          ) AND `lang` != (
            SELECT `lang`
            FROM `news`
            WHERE `id` = ".$id."
          ) AND `id` < ".$id."
          ORDER BY `id` DESC
          LIMIT 4
        ) `lower`
      ) OR `id` IN (
        SELECT * FROM (
          SELECT `id`
          FROM `news`
          WHERE `cat` = (
            SELECT `cat`
            FROM `news`
            WHERE `id` = ".$id."
          ) AND `lang` != (
            SELECT `lang`
            FROM `news`
            WHERE `id` = ".$id."
          ) AND `id` > ".$id."
          ORDER BY `id` ASC
          LIMIT 4
        ) `upper`
      )
      ORDER BY `id` DESC
    ";
    

    【讨论】:

    • @mellamokb 难以置信的丑陋,我确信有一种更有效的方法可以做到这一点,但现在我无法为我的生活弄清楚如何。至少不是在单个查询中,我想可以将最内层查询的结果缓存在变量中,但我怀疑额外的数据库流量会抵消收益。
    • 大声笑,以前从未见过这个错误:This version of MySQL doesn't yet support 'LIMIT &amp; IN/ALL/ANY/SOME subquery':sqlfiddle.com/#!2/dabe3/1
    • @DaveRandom - 谢谢,但收到错误 #1235 - 此版本的 MySQL 尚不支持 'LIMIT & IN/ALL/ANY/SOME 子查询' - 将在另一个环境中尝试。你的 MySQL 是什么版本的?
    • 好的。这似乎可行,但仍需要清理一下:sqlfiddle.com/#!2/1933d/3
    • @mellamokb 我发现了另一个(有点奇怪)解决方法here,它也是works。使用新查询编辑我的答案。
    【解决方案2】:

    这样的事情可能会奏效:

    $sql = "SELECT id, title FROM pubs 
            WHERE tip = ".$tip." AND lang <> ".$lang." 
            ORDER BY id DESC 
            LIMIT ".($id-4).",".($id+4);
    

    可能有一个更优雅的解决方案,但这可以完成工作。

    【讨论】:

    • LIMIT 6107, 6115(例如)将抓取6107th 行之后的6115 行。我认为这不能解决 OP 的问题。
    • 好吧,我想过这个,但 $id 并没有从选择中更改为 id - 它保持不变。 @康纳
    • @mellamokb - 这个想法是在 6111 之前和之后获取 4 行,但其中 id 不是结果值
    • @user1408669:我明白你想要什么,这是一个错误的答案。这就是我的观点。
    • @mellamokb - 是的,这不是我的问题的正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 2016-08-11
    相关资源
    最近更新 更多