[MySQL] Bereich um Primary Key selektieren

HerrHofrat

Grünschnabel
Hallo,

Also ich habe ein kniffeliges Problem:
Ich hab ein Foto Album und will 3 Foto-links selektieren. Sagen wir die Tabelle sieht so aus:
foto_id, gallery_id, src
Von einem weiß ich die foto_id (auto increment, primary key). Dazu will ich noch den Datensatz davor und den danach mit der selben gallery_id abfragen.

Werden sich jetzt die meisten denken: eh klar, mit foto_id+1 bzw foto_id-1. Aber was ist wenn die Fotos mit diesen IDs nicht im selben gallery-set sind? oder gar gelöscht worden sind?

Mein Ansatz bis jetzt ist:
1.Query
Select foto_id,src from foto where gallery_id = 1 AND foto_id = 5
2.Query (das davor)
Select foto_id,src from foto where gallery_id = 1 AND foto_id < 5 LIMIT 1
3.Query (das danach)
Select foto_id,src from foto where gallery_id = 1 AND foto_id > 5 LIMIT 1

aber da muss es ja was einfacheres mit einer query geben, oder?

Vielleicht kann mir ja wer helfen..

MfG Roman
 
Bisher kann ich dir schonmal sagen das dein Query für das davor unter Umständen nicht funktionieren wird. Das wird sich immer den ersten Eintrag der Tabelle schnappen. Ein ORDER dürfte vllt abhilfe schaffen.

Eine Frage: Ist dein PRIMARY ein UNSIGNED oder SIGNED?

EDIT: Wenn sie unsigned sind (so wie bei einer von meiner Tabelle) passt alles so in ein Query:

Code:
SELECT `templateID`, `templateURI`
FROM (
  SELECT `templateID`, `templateURI`
  FROM `templates`
  WHERE
    (5 - `templateID`) = (
          SELECT MIN(5 - `templateID`)
          FROM templates
          WHERE `templateID` <> 5 LIMIT 1)
    OR
    (5 - `templateID`) = (
          SELECT MAX(5 - `templateID`)
          FROM templates LIMIT 1)
    OR `templateID` = 5
  ) AS `tmp`

Kannst gut auf deine Übertragen.

NOCHMAL EDIT: Das hier fiel mir auch grad ein.
Ist schöner, da kann man die Weite um die gewünschte ID besser wählen:

Code:
SELECT `templateID`, `templateURI`
FROM `templates`
WHERE
  `templateID` = (
        SELECT `templateID`
        FROM `templates`
        WHERE `templateID` < 5
        ORDER BY `templateID` DESC
        LIMIT 1)
  OR
  `templateID` = 5
  OR
  `templateID` = (
        SELECT `templateID`
        FROM `templates`
        WHERE `templateID` > 5
        LIMIT 1)
 
Zuletzt bearbeitet:
Hi,

schreit das nicht eher nach 'nem UNION der 3 simplen Statements?

SQL:
(Select foto_id,src from foto where gallery_id = 1 AND foto_id = 5)
UNION
(Select foto_id,src from foto where gallery_id = 1 AND foto_id < 5 order by foto_id desc limit 1)
UNION
(Select foto_id,src from foto where gallery_id = 1 AND foto_id > 5 order by foto_id asc limit 1)

Kannst ja mal einen EXPLAIN auf die Queries machen.

LG
 
Zuletzt bearbeitet von einem Moderator:
Hm. Das ist jetz interessant.

Zuerst hab ich mir vorm Kopp gehauen weil ich nich an UNION gedacht hab.

Dann EXPLAIN angeguckt und musste feststellen das bei meiner letzten Variante ein index genutzt wird aber bei Union nicht.

Vor allem geht er mit der UNION-Variante bei einem SELECT durch die ganze Tabelle laut EXPLAIN, aber beide Varianten sind trotzdem nahezu zeitgleich fertig.

Hilfeee... Was isn nu schneller?
 
Hallo,

noch ne andere Möglichkeit wäre:
SQL:
mysql> select * from images;
+-----+------+
| id  | name |
+-----+------+
|   1 | A    |
|   2 | B    |
|   7 | BBB  |
|   9 | BB   |
|  10 | C    |
|  11 | CCC  |
|  12 | CC   |
|  14 | D    |
| 177 | E    |
+-----+------+
9 rows in set (0.00 sec)


select id,name from images where id = (select max(id) from images where 7-id > 0) or id = (select min(id) from images where 7-id < 0);
+----+------+
| id | name |
+----+------+
|  2 | B    |
|  9 | BB   |
+----+------+
2 rows in set (0.00 sec)


select id,name from images where id = (select max(id) from images where 10-id > 0) or id = (select min(id) from images where 10-id < 0);
+----+------+
| id | name |
+----+------+
|  9 | BB   |
| 11 | CCC  |
+----+------+

select id,name from images where id = (select max(id) from images where 14-id > 0) or id = (select min(id) from images where 14-id < 0);
+-----+------+
| id  | name |
+-----+------+
|  12 | CC   |
| 177 | E    |
+-----+------+
2 rows in set (0.00 sec)


select id,name from images where id = (select max(id) from images where 2-id > 0) or id = (select min(id) from images where 2-id < 0);
+----+------+
| id | name |
+----+------+
|  1 | A    |
|  7 | BBB  |
+----+------+
2 rows in set (0.00 sec)

Gruß Tom
 
Zurück