【问题标题】:SQL Selecting "Window" Around Particular RowSQL在特定行周围选择“窗口”
【发布时间】:2008-12-29 16:54:52
【问题描述】:

以前很可能有人问过这样的问题,但我想不出要搜索的字词。

我正在开发一个照片库应用程序,并希望显示 9 个缩略图来显示当前照片的上下文(在 3x3 网格中,当前照片位于中心,除非当前照片位于前 4正在显示的照片,在这种情况下,例如,如果当前照片是第二张我想选择照片 1 到 9)。例如,给定一个包含带有 id 的照片列表的相册:

1、5、9、12、13、18、19、20、21、22、23、25、26

如果当前照片是 19 岁,我还想查看:

9、12、13、18、19、20、21、22、23

如果当前照片是5,我还想查看:

1、5、9、12、13、18、19、20、21

我一直在想一些类似的事情:

SELECT *
FROM photos
WHERE ABS(id - currentphoto) < 5
ORDER BY id ASC 
LIMIT 25

但这不适用于 id 不连续的情况(如上面的示例),或者当前照片之前的照片不足的情况。

有什么想法吗?

谢谢,

Dom

附言如果有任何不清楚的地方,请发表评论,我会澄清这个问题。如果有人能想到一个更有用的标题来帮助其他人将来找到这个问题,那么也请发表评论。

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    可能只使用一个 UNION,然后在显示结果的程序代码中修剪掉额外的结果(因为这将在非边缘情况下返回 20 行):

    (SELECT 
         * 
    FROM photos
       WHERE ID < #current_id#
       ORDER BY ID DESC LIMIT 10)
    UNION
      (SELECT *
       FROM photos
       WHERE ID >= #current_id#
       ORDER BY ID ASC LIMIT 10)
    ORDER BY ID ASC
    

    编辑:根据 le dorfier 的建议,将 UNION 两侧的限制增加到 10。

    编辑 2:根据 Dominic 的建议进行修改以更好地反映最终实现。

    【讨论】:

    • 这是一个很好的、有用的技术。我过去曾将它与 MySQL 一起使用。要处理列表的末尾,您将没有足够的行:使用 LIMIT 10 并在程序代码中计算出选择。
    • 感谢 le dorfier,解决了限制问题,我会按照建议进行编辑。
    • 我最终做了与此非常相似的事情。我在 UNION 的结果上添加了“ORDER BY id ASC”,因此行按预期返回。您需要将第一个 ORDER 更改为 id DESC,否则前几行将始终返回。
    【解决方案2】:

    如果您使用的是 SQL Server,则可以使用 row_number() 函数为您提供行序索引并执行以下操作:

    declare @selected_photo integer;
    set @selected_photo = 5;
    
    declare @buffer_size integer;
    set @buffer_size = 2;
    
    select
       ph.rownum,
       ph.id
    from
       (select row_number() over (order by Id) as rownum, * from Photos) as ph
    where
       ph.rownum between case
                             when @selected_photo - @buffer_size < 1 then 1
                             else @selected_photo - @buffer_size
                          end
                          and @selected_photo + @buffer_size
    

    编辑: 这是一篇关于在 MySQL 中模拟 row_number() 函数的文章,将其与 这可能会为您提供所需的东西-我会尝试一下,但在工作中没有方便使用的 MySQL 数据库。 :-)

    http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/

    【讨论】:

    • 谢谢 Ron - 但我使用的是 MySQL,所以我认为我不能使用它 - 可以吗?
    • 我在 MySQL 文档中没有看到任何类似的东西......但我会继续探索。 :-)
    • @RonSavage:别打扰。 MySQL 是少数不支持窗口函数的 DBMS 之一。
    【解决方案3】:

    这是标准的“行排序”问题...如果您的数据库具有 rowId 功能,您可以使用它,否则您需要一个子查询来计算 ID 小于当前行 ID 的行数...比如这个:

    -- 假设@Id 是“中间”的 id 值

     Select *  From Photos P
     Where (Select Count(*) From Photos
             Where id <= P.Id)
         Between (Select Count(*) From Photos
                  Where id < @Id) - 4
            And  (Select Count(*) From Photos
                  Where id < @Id) + 4
    

    当评论提出专辑问题时,您希望将专辑谓词添加到每个子查询

       Select *  From Photos P
       Where (Select Count(*) From Photos
              Where album = @album
                And id <= P.Id)
         Between (Select Case When Count(*) < 4 
                          Then 4 Else Count(*) End
                  From Photos
                  Where album = @album
                     And id < @Id) - 4
            And  (Select Case When Count(*) < 4 
                          Then 4 Else Count(*) End
                  From Photos
                  Where album = @album
                      And id < @Id) + 4
    

    【讨论】:

    • 按专辑应该有额外的过滤器,否则不能解决问题 - 即它只适用于顺序 id。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 2014-07-06
    • 2021-08-22
    相关资源
    最近更新 更多