Odkazy: dibi | API reference

Forum: [česky] [english]

dibi fórum

tiny ‘n’ smart
database layer

Nejste přihlášen(a)

#1 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Ahoj vsem,

snad je nadpis odpovidajici tomu na co chci zeptat ;o)

Resim aktualizaci poradi pro zobrazeni, tj. mam v MySQL tabulku napr. XXX se sloupci primary_index(id), unique(poradi) a text.
Mam tam rekneme 1000 radku (zatim je poradi shodne s id) a ted mi uzivatel skrze fomular rekne, ze id=999 majici do ted poradi 999 bude mit nove poradi 10 → tj. potrebuji vygenerovat dotaz/dotazy na zmenu id v intervalu 10 az 999.

Jak to nejlepe udelat?

1.) vytvorit pro kazde ID update->execute() → to je asi trochu .. ehm … nestastne reseni

2.) vygenerovat pro kazde ID update, ale pouze je kumulovat a pak naraz provest ->execute() → to je asi vhodnejsi, ale napada Vas nekoho jako to udelat pres DibiFluent ?

3.) existuje nejaka lepsi treti cesta?

Diky za info.

Radek

Editoval ras (23. 11. 2011 22:29)


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#2 před 6 měsíci

Milo
dibi guru
Registrovaný: 4. 5. 2010
Příspěvky: 298

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Existuje několik dalších cest. Vše musí proběhnout uzavřené v transakci, zkráceně zapsáno takto:

a) Dočasně odstranit unikátní klíč

  • odstranit unikátní klíč
  • updaty pomocí poradi = poradi + 1 atd.
  • nahodit unikátní klíč

b) Druhým sloupcem a povolením NULL ve sloupci poradi

  • povolíš NULL ve sloupci pořadí
  • vytvoříš nový sloupec poradi_new
  • UPDATE poradi_new = poradi
  • srovnáš si jak potřebuješ sloupec poradi_new
  • UPDATE poradi = NULL
  • UPDATE poradi = poradi_new

c) Zvětšením pořadí nad aktuální maximum

  • $max = SELECT MAX(poradi)
  • updaty pomocí poradi = poradi + $max + 1 WHERE ... atd.

Vše má svoje výhody i nevýhody, záleží i na počtu řádků v tabulce. Já používám variantu c)

 

#3 před 6 měsíci

paranoiq
Moderator
Registrovaný: 14. 11. 2006
Příspěvky: 381

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

@ras: a na základě čeho má být pořadí změněno? nepřijde mi nijak užitečné určovat ad hoc pořadí u 1000 záznamů. pokud se pořadí řídí podle nějakého parametru záznamu, možná by bylo lepší využít toho

 

#4 před 6 měsíci

Milo
dibi guru
Registrovaný: 4. 5. 2010
Příspěvky: 298

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Doma jsem našel kus kódu k řešení c)

$old = 999;
$new = 10;

try{
        $db->begin();
        $limits = $db->query('SELECT MAX(poradi) AS max, MIN(poradi) AS min FROM tab')->fetch();

        $k = $limits->max - $limits->min + 1;

        $old = min(max($old, $limits->min), $limits->max);
        $new = min(max($new, $limits->min), $limits->max);

        if ($old < $new) {
                $db->query('UPDATE tab SET poradi = poradi + %i', $k, 'WHERE poradi > %i', $old, 'AND poradi <= %i', $new);
                $db->query('UPDATE tab SET poradi = %i', $new, 'WHERE poradi = %i', $old);
                $db->query('UPDATE tab SET poradi = poradi - %i - 1', $k, 'WHERE poradi > %i', ($old + $k), 'AND poradi <= %i', ($new + $k));

        } else {
                $db->query('UPDATE tab SET poradi = poradi + %i', $k, 'WHERE poradi < %i', $old, 'AND poradi >= %i', $new);
                $db->query('UPDATE tab SET poradi = %i', $new, 'WHERE poradi = %i', $old);
                $db->query('UPDATE tab SET poradi = poradi - %i + 1', $k, 'WHERE poradi < %i', ($old + $k), 'AND poradi >= %i', ($new + $k));
        }
        $db->commit();

} catch (Exception $e) {
        $db->rollback();
        throw $e;
}

 

#5 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Milo: Diky moc za zpusoby reseni … je to sice neco uplne jineho nez co jsem mel v planu, ale proc ne.

Kazdopadne muj puvodni plan bylo to provest nejak takto

$sql = "UPDATE XXX SET 'poradi' = 0 WHERE 'poradi' = 999";
<nejaky cyklus v PHP>
$sql .= "UPDATE XXX SET 'poradi' = 999 WHERE 'poradi' = 998";
$sql .= "UPDATE XXX SET 'poradi' = 998 WHERE 'poradi' = 997";
.
.
.
$sql .= "UPDATE XXX SET 'poradi' = 12 WHERE 'poradi' = 11";
$sql .= "UPDATE XXX SET 'poradi' = 11 WHERE 'poradi' = 10";
</nejaky cyklus v PHP>
$sql .= "UPDATE XXX SET 'poradi' = 10 WHERE 'poradi' = 0";

// V tuto chvili mam "kvanta" SQL prikazu v 1 promenne a zbyva udelat jeden hromadny EXECUTE()

$sql->execute();

Akorat neutisim, zda to, co je obsazeno v to cyklu, je mozne provest v DibiFluent, tj. jak tam naplnit tu promennou?

paranoiq: poradi je na libovuli uzivatele ;o), takze me jina cesta nenapada, nez menit ty kvanta zaznamu, resp. cesta by asi byla pres vytvoreni nejake vlastni logiky zapisu poradi, ale to se mi nechce resit ;o)


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#6 před 6 měsíci

Milo
dibi guru
Registrovaný: 4. 5. 2010
Příspěvky: 298

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Myslím, že to co jsem poslal bude rychlejší. Ale pokud to chceš dělat UPDATE ....; UPDATE ....; UPDATE ....;, poskládat se to dá. Jenže MySQL driver nepodporuje multiquery, takže to přes něj neproleze. Můžeš si upravit MySQLi, psal jsem tu jak cca na to. A další věcí je maximální délka SQL dotazu (nevím jestli je u MySQL nějak omezená), protože pro 1000 řádků to bude román. Takže bych to tak vůbec nedělal :)

$fluent = dibi::command();
for ($i = 10; $i > 0; $i--) {
        $f = dibi::update('XXX', array('poradi' => $i))->where(array('poradi' => $i - 1));
        $fluent->{''}((string) $f . ';');
}

$fluent->test();

 

#7 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Diky za info.

Ja to ted resim nad tabulkou o par radcich … takze vykon neni problem … ale umyslne jsem napsal tisic, protoze tam uz vykon je neco, co se musi resit. Tady u tech par radku je to fuk.

Jeste jednou diky.

Radek


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#8 před 6 měsíci

HosipLan
dibi guru
Registrovaný: 1. 6. 2009
Příspěvky: 2630

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Rozhodně není dobré psát 1000 dotazů pro 1000 řádků, lepší je nastavit to pomocí intervalů.

Ty musíš změnit ty dva konrétní řádky, prohodit je, posunout je… A pak ty zbývající, pokud je potřeba je posouvat, posuneš pomocí

UPDATE xxx SET `order` = `order` + 1 /* nebo -1 */ WHERE `order` <= $x AND `order` > $y

Neptej se, jestli se můžeš ptát | Blog | Twitter | GitHubCMS Kdyby

Nette Jabber Room – nette@conf.netlab.cz , všichni jste vítáni

 

#9 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Super, ja uplne vedel, ze neco je … ale fakt jsem to nedokazal vymyslet. ;o) To je tak, kdyz ma nekdo Filipa ;o)


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#10 před 6 měsíci

Milo
dibi guru
Registrovaný: 4. 5. 2010
Příspěvky: 298

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

@HosipLan: Jenže on má na tom sloupci unikátní klíč. Takže order = order + 1 nemusí proběhnout. Je vhodnější daný interval přesunout nad maximum a pak zpět o jedno větší/menší. Viz. kód k řešení c).

 

#11 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Milo …ja to jeste nezkousel → pak dam vedet, ale podle toho HosipLanova popisu bych rekl (logickym usudkem), ze to musi fungovat … az to vyzkousim, tak dam vedet.


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#12 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Takze vyzkouseno → a vysledek jsou 3 dotazy do DB bez ohledu na to, kolik radku se ma menit a UNIQUE index na danem sloupci … klidne to zvladne tech 1000 radku.

Mejme nasledujici tabulku XXX

id / poradi / text
1  /    1   /  aaa
2  /    2   /  bbb
3  /    3   /  ccc
4  /    4   /  ddd
5  /    5   /  eee

**Vzdy je nutne rozlisit, zda je novePoradi vetsi/mensi nez puvodniPoradi → podle toho se pak upravuje update

Pozadavek c.1 … novePoradi < puvodniPoradi

→ eee ma byt prvni → poradi 5 ⇒ 1

// zmenim docasne poradi u radku, ktery se ma primarne zmeni, tj. u poradi c. 5
UPDATE XXX SET `poradi` = 0 WHERE `poradi` = 5
// ted posuneme vsechny radky, kterych se pozadavek na zmenu poradi dotyka, tj. radky v intervalu <nova pozadovana hodnota> az <puvodni hodnota - 1>
// DULEZITE je zde provest to ORDER BY .. jinak by to narazilo na UNIQUE() index
UPDATE XXX SET `poradi` = `poradi` + 1 WHERE `poradi` >= 1 AND `poradi` < 5 ORDER BY poradi DESC;
// nastavime pro radek, ktereho se zmena primarne tyka novou, tj. pozadovanou, hodnotu
UPDATE XXX SET `poradi` = 1 WHERE `poradi` = 0

a ted ukazka opacneho postupu

Pozadavek c.2 … novePoradi > puvodniPoradi

v navaznosti na predchozi pozadavk → eee ma byt ve finale treti → poradi 1 ⇒ 3

// zmenim docasne poradi u radku, ktery se ma primarne zmeni, tj. u poradi c. 1
UPDATE XXX SET `poradi` = 0 WHERE `poradi` = 1
// ted posuneme vsechny radky, kterych se pozadavek na zmenu poradi dotyka, tj. radky v intervalu <puvodni hodnota +1> az <nova pozadovana hodnota>
// DULEZITE je zde provest to ORDER BY .. jinak by to narazilo na UNIQUE() index
UPDATE XXX SET `poradi` = `poradi` - 1 WHERE `poradi` > 1 AND `poradi` <= 3 ORDER BY poradi ASC;
// nastavime pro radek, ktereho se zmena primarne tyka novou, tj. pozadovanou, hodnotu
UPDATE XXX SET `poradi` = 1 WHERE `poradi` = 0

Vysledek po 2 upravach

id / poradi / text
1  /    1   /  aaa
2  /    2   /  bbb
3  /    4   /  ccc
4  /    5   /  ddd
5  /    3   /  eee

= 6 SQL dotazu → mene to myslim ani nejde

Diky vsem za pomoc → pokud nekdo ma v rukavu jeste neco efektivnejsiho, tak sem s tim ;o)


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#13 před 6 měsíci

Milo
dibi guru
Registrovaný: 4. 5. 2010
Příspěvky: 298

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Wow! Tak s tím ORDER BY u mě MySQL dost zabodovalo. To jsem netušil. V tom případě HosipLanovo řešení je to nejsnazší.

Editoval Milo (25. 11. 2011 12:07)

 

#14 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Ja taky ne, ale resil jsem, jak je donutit, aby mi to precislovavalo v poradi jak je potreba, jinak to porad narazelo na ten UNIQUE() index → tak jsem to zkusil ;O)


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#15 před 6 měsíci

paranoiq
Moderator
Registrovaný: 14. 11. 2006
Příspěvky: 381

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

ras napsal(a):
paranoiq: poradi je na libovuli uzivatele ;o), takze me jina cesta nenapada, nez menit ty kvanta zaznamu, resp. cesta by asi byla pres vytvoreni nejake vlastni logiky zapisu poradi, ale to se mi nechce resit ;o)

u 20–50 položek bych to ještě chápal. ale v 1000 už se ten chudák přeci musí sám ztrácet. tohle je případ, kdy bych já uživateli vysvětloval, že to co potřebuje asi není to co chce…

 

#16 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Ted jeste zkoumam jak to v DibiFluent zapsat

UPDATE XXX SET `poradi` = `poradi` + 1 WHERE `poradi` >= 1 AND `poradi` < 5 ORDER BY poradi DESC;

protoze kdyz napisu

$this->db->update($tabulka, array('poradi' => 'poradi + 1'))->/....

tak je vysledny SQL

UPDATE XXX SET 'poradi' = 'poradi + 1' WHERE ...

a ja potrebuji

UPDATE XXX SET 'poradi' = poradi + 1 WHERE ...

Nejaky navrh by byl, resp. jiny nez to resit pres dibi::query ci dibi::command?


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

#17 před 6 měsíci

Milo
dibi guru
Registrovaný: 4. 5. 2010
Příspěvky: 298

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

Už se tu několikrát řešilo…

$this->db->update($tabulka, array('poradi%sql' => '[poradi] + 1'))...

 

#18 před 6 měsíci

ras
Člen
Registrovaný: 27. 10. 2010
Příspěvky: 88

Re: Jde v DibiFluent skladat SQL prikaz aneb efektivita dotazu?

MILO Pres dibi::command jsem na to vcera prisel …

$this->db->command()->update($tabulka)->where("poradi >= %i", $novePoradi)->AND("poradi < %i", $puvodniPoradi)->orderBy("poradi")->desc()->set("poradi = poradi + 1")->execute();

… ale, protoze jsem vcera musel od PC, tak jsem se k procitani fora nedostal, takze diky za usetreny cas. Tvoje reseni se mi libi vice.

DIKY za vse v tomto vlaknu !


Shánění zakázek je pro mě jednodušší než samotná tvorba webů ⇒ hledám partnera především na dlouhodobou spolupráci.

 

Zápatí