SQL потянув строку для следующей или предыдущей строки текущей строки - PullRequest
12 голосов
/ 11 августа 2009
id    |  photo title     |  created_date

XEi43 |  my family       |  2009 08 04
dDls  |  friends group   |  2009 08 05
32kJ  |  beautiful place |  2009 08 06
EOIk  |  working late    |  2009 08 07 

Скажи, у меня есть идентификатор 32kJ. Как получить следующий или предыдущий ряд?

Ответы [ 6 ]

17 голосов
/ 13 мая 2010

Это то, что я использую для поиска предыдущих / следующих записей. Любой столбец в вашей таблице может быть использован в качестве столбца сортировки, и не требуется никаких объединений или неприятных хаков:

Следующая запись (дата больше текущей записи):

SELECT id, title, MIN(created) AS created_date
FROM photo
WHERE created >
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created ASC
LIMIT 1;

Предыдущая запись (дата меньше текущей записи):

SELECT id, title, MAX(created) AS created_date
FROM photo
WHERE created <
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created DESC
LIMIT 1;

Пример:

CREATE TABLE `photo` (
    `id` VARCHAR(5) NOT NULL,
    `title` VARCHAR(255) NOT NULL,
    `created` DATETIME NOT NULL,
    INDEX `created` (`created` ASC),
    PRIMARY KEY (`id`)
)
ENGINE = InnoDB;

INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('XEi43', 'my family',       '2009-08-04');
INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('dDls',  'friends group',   '2009-08-05');
INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('32kJ',  'beautiful place', '2009-08-06');
INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('EOIk',  'working late',    '2009-08-07');

SELECT * FROM photo ORDER BY created;
+-------+-----------------+---------------------+
| id    | title           | created             |
+-------+-----------------+---------------------+
| XEi43 | my family       | 2009-08-04 00:00:00 |
| dDls  | friends group   | 2009-08-05 00:00:00 |
| 32kJ  | beautiful place | 2009-08-06 00:00:00 |
| EOIk  | working late    | 2009-08-07 00:00:00 |
+-------+-----------------+---------------------+


SELECT id, title, MIN(created) AS next_date
FROM photo
WHERE created >
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created ASC
LIMIT 1;

+------+--------------+---------------------+
| id   | title        | next_date           |
+------+--------------+---------------------+
| EOIk | working late | 2009-08-07 00:00:00 |
+------+--------------+---------------------+

SELECT id, title, MAX(created) AS prev_date
FROM photo
WHERE created <
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created DESC
LIMIT 1;

+------+---------------+---------------------+
| id   | title         | prev_date           |
+------+---------------+---------------------+
| dDls | friends group | 2009-08-05 00:00:00 |
+------+---------------+---------------------+
2 голосов
/ 26 октября 2009

Вы хотели следующий / предыдущий ряд по дате? Если это так, вы можете сделать это:

select MyTable.*
from MyTable
join
  (select id
   from MyTable
   where created_date < (select created_date from MyTable where id = '32kJ')
   order by created_date desc, id desc
   limit 1
  ) LimitedTable on LimitedTable.id = MyTable.fund_id;
2 голосов
/ 11 августа 2009

Я понимаю, что вы используете MySQL, но просто для справки, вот как вы бы это сделали, используя аналитические функции Oracle LEAD и LAG:

select empno, ename, job,
  lag(ename, 1) over (order by ename) as the_guy_above_me,
  lead(ename, 2) over (order by ename) as the_guy_two_rows_below_me
from emp
order by ename

Полагаю, есть причина, по которой Oracle стоит денег, а MySQL бесплатен ...: -)

Эта страница показывает вам , как эмулировать аналитические функции в MySQL .

1 голос
/ 08 сентября 2011

Используя у Майка MAX / MIN трюк, мы можем совершать предыдущие \ следующие прыжки для всех видов вещей. Этот пример msAccess вернет предыдущее закрытие для каждой записи в таблице данных фондового рынка. Примечание: <= 'для выходных и праздничных дней. </p>

SELECT 
   tableName.Date,
   tableName.Close,
   (SELECT Close 
      FROM tableName 
      WHERE Date = (SELECT MAX(Date) FROM tableName 
                     WHERE Date <= iJoined.yesterday)
   ) AS previousClose
FROM 
 (SELECT Date, DateAdd("d",-1, Date) AS yesterday FROM tableName)
  AS iJoined 
INNER JOIN 
    tableName ON tableName.Date=iJoined.Date;

... «вчера» демонстрирует использование функции ( Date-1 ) jump; мы могли бы просто использовать ...

(SELECT Date FROM tableName) AS iJoined
  /* previous record */
(SELECT MAX(Date) FROM tableName WHERE Date < iJoined.Date)
  /* next record */
(SELECT MIN(Date) FROM tableName WHERE Date > iJoined.Date)

Хитрость в том, что мы можем предыдущий \ следующий # из независимо от (s) с MAX \ MIN и функцией перехода ()

0 голосов
/ 06 октября 2012

Я рассматривал id как первичный ключ в таблице (и как «номер строки») и использовал его для сравнения каждой записи с записанной ранее. Следующий код должен работать.

CREATE SCHEMA temp
create table temp.emp (id integer,name varchar(50), salary  varchar(50));
insert into temp.emp values(1,'a','25000');
insert into temp.emp values(2,'b','30000');
insert into temp.emp values(3,'c','35000');
insert into temp.emp values(4,'d','40000');
insert into temp.emp values(5,'e','45000');
insert into temp.emp values(6,'f','20000');

select * from temp.emp

SELECT
    current.id, current.name, current.salary,
    case 
        when current.id = 1 then current.salary 
        else 
            case
                when current.salary > previous.salary then previous.salary
                else current.salary  
            end
     end
FROM
    temp.emp AS current
    LEFT OUTER JOIN temp.emp AS previous
    ON current.id = previous.id + 1
0 голосов
/ 11 августа 2009

Ужасный хак - мне это не нравится, но может сработать ..

with yourresult as
(
select id, photo_title, created_date, ROW_NUMBER() over(order by created_date) as 'RowNum' from your_table
)
-- Previous
select * from yourresult where RowNum = ((select RowNum from yourresult where id = '32kJ') -1)
-- Next
select * from yourresult where RowNum = ((select RowNum from yourresult where id = '32kJ') +1)

Что пригодится?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...