SQL Selecting “Window” Around Particular Row

后端 未结 3 583
礼貌的吻别
礼貌的吻别 2021-01-02 11:04

It\'s quite possible a question like this has been asked before, but I can\'t think of the terms to search for.

I\'m working on a photo gallery application, and want

相关标签:
3条回答
  • 2021-01-02 11:36

    This is standard "Row ordering" problem... If your database has rowId capability you can use that, otherwise you need a subquery that counts the numnber of rows with Ids less than the id of the current row... like this:

    -- asssuming @Id is value of id in the "middle"

     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
    

    As a comment raised the album issue you would want to add album predicate to each subquery

       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
    
    0 讨论(0)
  • 2021-01-02 11:44

    Probably could just use a UNION, and then trim off the extra results in the procedural code that displays the results (as this will return 20 rows in the non-edge cases):

    (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
    

    EDIT: Increased limit to 10 on both sides of the UNION, as suggested by le dorfier.

    EDIT 2: Modified to better reflect final implementation, as suggested by Dominic.

    0 讨论(0)
  • 2021-01-02 11:49

    If you are using SQL Server, you can use the row_number() function to give you the row order index and do something like this:

    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
    

    Edit: Here is an article on simulating the row_number() function in MySQL, combining that with this might get you what you need - I'd try it but don't have a MySQL db handy to play with at work. :-)

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

    0 讨论(0)
提交回复
热议问题