LINUX.ORG.RU

помогите составить SQL запрос


0

0

Приветствую!

Есть такая табличка:

CREATE TABLE `tbl_photo` (
    `id`  MEDIUMINT(10) AUTO_INCREMENT NOT NULL,
    `genre_id`  MEDIUMINT(10) NOT NULL,
    `gallery_id`  MEDIUMINT(10) NOT NULL,
    `article_id`  MEDIUMINT(10) NOT NULL,
    `filename` VARCHAR(40) NOT NULL,
    PRIMARY KEY(`id`)
) ENGINE=MyISAM, DEFAULT CHARSET=utf8;

Как понятно - это фотки.

Из неё надо извлечь: 1. Одну фотку (WHERE id=n) 2. Предыдущую фотку 3. Следующую фотку

Это надо сделать одним запросом в строчку.

Я намудрил как-то так:

SELECT MAX(pr.id) AS prev ,ph.id AS now, MIN(nx.id) AS next 
FROM tbl_photo AS ph LEFT JOIN tbl_photo AS pr ON pr.id < ph.id 
LEFT JOIN tbl_photo AS nx ON nx.id > ph.id WHERE ph.id=12;
12 - для примера. Вроде делает, но правильно отрабатывает только для id. Остальные поля таблицы pr, если их запросить, выдаёт некорректно (оно понятно, почему)

Подскажите мне как это сделать? Может, существует более простой способ? БД - MySQL.


Ответ на: комментарий от Anoxemian

Наверно потому что не всегда между соседними ID будет интервальчик в 1.

anonymous
()

Пробуй

select t1.id, 
       (select max(t2.id) 
          from tbl_photo t2 
         where t2.id < t1.id) pr,
       (select min(t3.id) 
          from tbl_photo t3 
         where t3.id > t1.id) nx
  from tbl_photo t1 
  where t1.id = 12
aydar ★★★★★
()
Ответ на: комментарий от Anoxemian

потому что id могут следовать не по порядку (к примеру, кто-то удалил фото) 9,10,15,16,17,20...

solom
() автор топика
Ответ на: Пробуй от aydar

А вот Ваш пример, по ходу дела работает.

solom
() автор топика
Ответ на: Пробуй от aydar

Посмотрел, проверил. Друге столбцы корректно не извлекаются. Тут должно быть что-то ещё.

solom
() автор топика
Ответ на: комментарий от solom

Не самый оптимальный и изящный вариант, но работает

select a.*, b.*, c.*
  from (select t1.*,
               (select max(t2.id) from tbl_photo t2 where t2.id < t1.id) pr,
               (select min(t3.id) from tbl_photo t3 where t3.id > t1.id) nx
          from tbl_photo t1
         where t1.id = 12) a,
       tbl_photo b,
       tbl_photo c
 where a.pr = b.id
   and a.nx = c.id

aydar ★★★★★
()

Вариант в лоб такой:

select * from tbl_photo where id in ((select id from tbl_photo where id < 12 order by id desc limit 1), 12, (select id from tbl_photo where id > 12 order by id limit 1));

Вполне возможно, что возможны и более красивые варианты

Tigger ★★★★★
()
Ответ на: комментарий от Tigger

Вобчем, пока направление мыслей такое же

solom
() автор топика
Ответ на: комментарий от aydar

Хороший пример (врядли тут можно придумать что-то красивее), но имеет недостаток: на крайних значениях ничего не выводит.

solom
() автор топика

select * from tbl_photo where id=12 or id=(
select max(id) from tbl_photo where id<12) or id=(
select min(id) from tbl_photo where id>12);

josephson ★★
()
select MAX(CASE id.side WHEN 'l' THEN id.id ELSE NULL END) as prev_id
      ,MAX(CASE id.side WHEN 'l' THEN tbl.genre_id ELSE NULL END) as prev_gnr
      ,MAX(CASE id.side WHEN 'c' THEN id.id ELSE NULL END) as now_id
      ,MAX(CASE id.side WHEN 'c' THEN tbl.genre_id ELSE NULL END) as now_gnr
      ,MAX(CASE id.side WHEN 'r' THEN id.id ELSE NULL END) as next_id
      ,MAX(CASE id.side WHEN 'r' THEN tbl.genre_id ELSE NULL END) as next_gnr
      
from tbl_photo tbl,

(select min(id) as id, 'l' as side from tbl_photo where id < 12
 union
 select max(id) as id, 'r' as side from tbl_photo where id > 12
 union
 select 12      as id, 'c' as side from dual /* или какая там у вас */) id

where tbl.id = id.id
ttnl ★★★★★
()

Более простой способ - явно запихивать id предыдущей и последующей фотографии:
...
id_prev MEDIUMINT(10) NULL,
id_next MEDIUMINT(10) NULL,
...
При добавлении и удалении обновлять их (желательно - триггером)

Дом. задание: проверить, соответствует ли схема третьей нормальной форме.

svu ★★★★★
()
Ответ на: комментарий от solom

Зависит от того, что нужно оптимизировать. Попробуйте придумать более быстрое решение по производительности?

svu ★★★★★
()
select * from tbl_photo where id >= (select max(id) from tbl_photo where id < 12) limit 3;

p.s.

select * from tbl_photo where id >= (select id from tbl_photo where id < 12 order by id desc limit 1 offset 2) limit 7;

dimon555 ★★★★★
()

а зачем, интересно, именно так надо извлекать данные из БД ?

x905 ★★★★★
()
Ответ на: комментарий от josephson

select * from tbl_photo where id in ((select max(id) from tbl_photo where id<12),12,(select min(id) from tbl_photo where id>12));

?

josephson ★★
()
Ответ на: комментарий от solom
select a.*, b.*, c.*
  from (select t1.*,
               (select max(t2.id) from tbl_photo t2 where t2.id < t1.id) pr,
               (select min(t3.id) from tbl_photo t3 where t3.id > t1.id) nx
          from tbl_photo t1
         where t1.id = 12) a
  left outer join tbl_photo b
    on a.pr = b.id
  left outer join tbl_photo c
    on a.nx = c.id
aydar ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.