Seznam s pořadím v DB

Tak už vím, jak tady někdo nedávno nadával na dlouhej post, že se mu smazal, kvůli vypršení session. Právě jsem si dal taky. Hmmm.

Takže ještě jednou prosím o radu či vaše zkušenosti.

Nevím si rady s utvořením seznamu s pořadím. Míněno, že v DB budu ukládat pořadí, a to pořadí pak budu chtít být schopen měnit (jak jinak asi:)).

Tzn ze seznamu:
(id, poradi)
A 1
B 2
C 3

být schopen udělat

A 1
B 3
C 2

Jako první slabinu vidím slabou integritu, ptž moje tabulka bude ve skutečnosti
(id, f_id, poradi)

A 2 1
B 2 2
C 3 1
D 3 3
E 3 2

Tzn takový neohrabaný, ptž to minimálně nebudu moct pojistit na straně DB max z toho udělám index.

A druhá věc je, že zatím nevidím jinou možnost pro změnění pozice, než 4 dotazy:
2x select pro zjištění id z pozic a 2x update pro změnu těch pozic identifikovanou těma id

A nebo něco na styl:
UPDATE fotoreference SET poradi = '2' WHERE poradi = '1' AND f_id='$fid';
UPDATE fotoreference SET poradi = '1' WHERE poradi = '2' AND f_id='$fid';
ovšem logicky nutno spojit do jednoho, ptž takto to evidentně nejde...

Jakkýkoli nápad ocením, případně dovysvětlím.
Díky
J.
Moc moudrý z toho dotazu nejsem. Takže jen tak plácnu, co si o tom myslím.

SELECT by ti měl stačit jeden, UPDATE budeš potřebovat pro každý řádek jeden.


Nicméně, zkus se zamyslet, jestli opravdu potřebuješ ukládat pořadí a to měnit. Pořadí se přece podle NĚČEHO určuje. Tak si ukládej to NĚCO a pak nechej databázi, ať ti pořadí podle toho NĚČEHO vygeneruje.
SELECT * FROM ... WHERE id IN (1,5) LIMIT 2
nebo
SELECT * FROM ... WHERE (poradi = '1' AND f_id='$fid') OR (poradi = '2' AND f_id='$fid') LIMIT 2

UPDATE 2x, pro kazdou polozku

Co se tyce poradi...
id 2 A
id 3 B
vymena poradi
SELECT
data 0, data 1
UPDATE WHERE id=3 data0
UPDATE WHERE id=2 data1
cili vymenovat podle autoincrementu indexu navzajem. Pokud jsou velka data, tak viz prvni zpusob, pridat sloupec a ten prepisovat.

zbi (knizky.unas.cz)
predstav si drag drop system a prehazujes polozky menu. Pak to nemas ani podle jmena, ani podle poradi v SQL, ale podle nejakeho dalsiho poradi, sloupec navic.
Díky moc za tipy. Ten select jsem přehlídl. Jasně, že stačí jeden.

zbi: Konkrétně to budu používat pro fotoreference pro různé technologie, kde jednotlivý fotoreference musí jít v posunovat ve své technologii (ne jen podle toho, kdy tam byly vložený, ale dle přání redakčním systémem kdykoliv měnit).

peta:
tak abych se přiznal, tak ten druhej způsob jde mimo mě. Mohl bys mě to přiblížit? Myslíš, že budu mít (viz výše) pro každou technologii vlastní seznam, kde budu mít autoincrementovej sloupec, a pak budu všechny technologie joinovat? To asi ne že:))
Reálně opravdu nepůjde o moc dat, takže jestli je něco rychlejšího, tak bych to rád zvážil.
jj, pořadí, to je věc. To jsem taky nedávno řešil..
sloupeček navíc, pro pořadí je nutnost (podku někdo určuje pořadí).
No a pak to příjde. Dá se to udělat třeba takto: (osobně jsem potřeboval pořadí začínat od 1 a mít nepřerušenou řadu)
- pokud přidávám, najdu max a přidá jedničku (teoreticky může být autoincrement, ale musí se korigovat při mazání).
- pokud posouvám, tak vezmu číslo odkud kam a podle směru posunu o 1 daným směrem blok dat (jeden update), změna pořadí toho řádku, který posouvám (druhý update) - na každý posun v libovolném počtu řádků v tabulce tedy postačí 2x update.
- pokud řádek mažu, tak číslo v podstatě posunu nakonec (tzn. 1x delete 1x update.

pokud se řeší pořadí ještě v závislosti na nějakém parametru (já jsem např. řešil rok), tak je to malinko složitější, ale ne moc...

Ještě při posunování kolem začátku a konce tabulky pozor na okrajové podmínky, tedy aby někde nevznikl ř. č. 0 (pokud má být minimální 1) a obdobně na druhém konci tabulky.
Koukám, že je to opravdu taková bída, jak jsem myslel :)) co už. Aspoň to, co už mám rozpracovaný nepřijde nazmar.

"pokud posouvám, tak vezmu číslo odkud kam a podle směru posunu o 1 daným směrem blok dat (jeden update), změna pořadí toho řádku, který posouvám (druhý update) - na každý posun v libovolném počtu řádků v tabulce tedy postačí 2x update."
--- jaká je syntaxe pro posun bloku dat? A celkově, jak to myslíš? To bude asi to, co říkal Peta a já to nepochopil. A nebude to ve výsledku horší po stránce zátěže než update podle zjištěných unique_id?
Mo6n8 bzch místo nějakého přerovnávání bloků kódu, nebo přidávání dalších sloupečků zkusil využít toto:
function getBorders(&$array, $id){
  $borders = array(NULL, NULL);
  if(!array_key_exists($id, $array)) return $borders;
  for($i=0; $i<count($array); $i++){
    if(key($array) == $id) {
      if($i<(count($array)-1)) $borders[1] = next($array);
      break;
    }
    $borders[0] = current($array);
    next($array);
  }
  return $borders;
}
$borders = getBorders($values, $id);

LEGENDA:
sákryš ... zase mi to uřízlo kus příspěvku :|

LEGENDA:
 $array je pole všech ID získaných z db.
 $id je aktuální ID
 $borders vrací předchozí a následující existující ID.
Tom: to je ale trošku dost offtopic :) ale tak neva...
No, jsem poobědě, tak je spousta krve v trávicí soustavě, nic méně se pokusím:
vezměme tabulku
create table tab (
id int,
obsah varchar(moc),
poradi int
)
dejme tomu, že @a je proměnná, která značí pořadové číslo (poradi), řádku, který je první z bloku, který se má posunovat, @b je poseldní.

pak posun bloku mezi pořadovým číslem @a a @b bude pravděpodobně vypadat následovně:
update tab set
poradi = poradi + sign(@b - @a)
where poradi between @a and @b

tím se to šoupne.

pak je třeba nastavit číslo pořadí toho místa, kde vznikla díra.

Znovu připomínám, že je potřeba dát pozor na okrajové podmínky a správně nastavit to @a a @b.
sing() je fce, viz manuál.

Není to úplně přesně, je to jenom návod, jak bych to řešil. Ale ty jsi určitě šikovný a zbytek si hravě doděláš sám.
Jako šikovnej bych se nanazval. Jsem programátor - samouk :)) Takže spíš nešikovnej. Nicméně toto je super návod a podle toho už to zmáknu.
Takže díky moc
Myslím, že v Pátek jsem to naškrábal, takže pro úplnost to tady uvedu, kdyby se nad tím v budoucnu nechtělo někomu přemýšlet :)

Uvádím jen podstatnou část. Stále potřeba ty podmínky, ale to už si napíše každej, i když toto asi taky :))

//za predpokladu smazani polozky volat. "Urovnava" poradi.
private function moveBlockDown($gid,$pos_id) {
$max_id = $this->getLastRef($gid);
$this->DB->qry("UPDATE table SET poradi=poradi-1 WHERE g_id='$gid' AND poradi BETWEEN $pos_id AND $max_id");
}

//zamenuje poradi polozek
private function switchUp($rid,$posid) {
$pos_up = $posid-1;
$result = $this->DB->qry("SELECT rid FROM table WHERE poradi='$pos_up' LIMIT 1;");
$line = mysql_fetch_assoc($result);
$up_id = $line['rid'];
$this->DB->qry("UPDATE fotoreference SET poradi='$posid' WHERE rid='$up_id';");
$this->DB->qry("UPDATE fotoreference SET poradi='$pos_up' WHERE rid='$rid';");
}

Všem za rady moc děkuju. Zvláštní dík patří Markovi.