Opakující se SQL select a nekonkrétní výběr sloupců
- thorewi
- Člen | 84
Zdravím,
mám tento kód:
{foreach $rooms as $room}
{foreach $room->related('reservation_room') as $reservation_room}
<span class="names" n:inner-foreach="$reservation_room->related('reservation_room_guest') as $reservation_room_guest">
{? $guest = $reservation_room_guest->guest}
{$guest->surname}{sep}, {/sep}
</span>
{/foreach}
{/foreach}
a při každém průchodu se mi provede tento dotaz:
SELECT `id`, `surname`, `firstname`, `company_id`, `email`, `street`, `zip`, `city`, `country_id`
FROM `guest`
WHERE (`id` IN (51, 155, 58, 160, 103, 124, 187, 161, 84, 237, 209, 226, 128, 235, 246, 247, 236,
238, 239, 241, 242, 243, 240, 248, 249, 250, 245, 170, 252, 258, 259, 251, 262, 263, 260, 211, 144,
56, 142, 76, 97, 199, 64, 134, 89, 126, 147, 95, 120, 201, 140, 111, 203, 130, 60, 78, 93, 136, 223,
62, 72, 80, 91, 132, 205, 165, 54, 157, 99, 117, 163, 198, 87, 207, 232, 66, 173, 52, 70, 105, 224,
138, 68, 171, 149, 175, 268, 269, 270, 153, 271, 253, 214, 227, 261, 282, 283, 265, 264, 254, 255,
273, 278, 233, 234, 280, 286, 256, 288, 298, 275, 297, 219, 295, 299, 301, 300, 302, 303, 304, 305,
306, 307, 308, 190, 309, 310, 229, 312, 313, 316, 311, 315, 314, 317, 181, 318, 319, 296, 267, 179,
177, 218, 320, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 185, 244, 279, 281, 230, 257, 231,
276, 335, 291, 292, 337, 338, 339, 342, 343, 336, 351, 284, 350, 346, 345, 349, 285, 347, 228, 289,
354, 355, 340, 322, 348, 290, 352, 353, 294, 293))
- Neměl by se tento dotaz provést jen jednou?
- Něměl by se vybírat jen sloupec surname, když žádný jiný nepoužívám?
Mám nejnovější verzi Nette z Githubu (dnes stáhlou). Myslím ale, že se to dělalo i se staršími verzemi.
Editoval thorewi (24. 1. 2013 22:20)
- thorewi
- Člen | 84
- No nefunguje mi to nikde, nejenom v tomto konkrétním případě, ale v jiných případech i úplně jiných projektech. Může mi někdo potvrdit, že když má v šabloně foreach ve foreachi a v druhém foreachi má related, tak se mu ten select provede jen jednou (s posledním verzí Nette z Githubu)?
- thorewi
- Člen | 84
Ok tak pridavam nove info:
U tohoto kodu se projevuji oba dvy vyse zminene problemy:
{foreach $rooms as $room}
{foreach $room->related('reservation_room') as $reservation_room}
{foreach $reservation_room->related('reservation_room_guest')->select('guest.surname') as $reservation_room_guest}
{$reservation_room_guest->id}
{/foreach}
{/foreach}
{/foreach}
Pokud ale pridam (jak podotkl Hrach) ->select(‚guest.surname‘), oba dva problemy jsou vyreseny:
{foreach $rooms as $room}
{foreach $room->related('reservation_room') as $reservation_room}
{foreach $reservation_room->related('reservation_room_guest')->select('guest.surname') as $guest}
{$guest->surname}
{/foreach}
{/foreach}
{/foreach}
Díky za radu.
- thorewi
- Člen | 84
Jen podotknu že to neni mozna uplne adekvatni reseni, protoze upraveny dotaz mi dela tento SQL select:
SELECT `reservation_room_guest`.`reservation_room_id`, `guest`.`surname`
FROM `reservation_room_guest`
LEFT JOIN `guest` ON `reservation_room_guest`.`guest_id` = `guest`.`id`
WHERE (`reservation_room_guest`.`reservation_room_id` IN (389, 390, 391, 392, 393, 394, 395, 396,
397, 398, 399, 400, 401, 402, 403, 404, 405, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417,
418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 436, 438, 439,
440, 441, 442, 443, 444, 445, 447, 448, 449, 450, 451, 453, 454, 462, 463, 464, 465, 466, 467, 478,
479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 492, 493, 494, 495, 496, 497, 498, 499,
500, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520,
521, 522, 524, 525, 526, 527, 532, 533, 534, 535, 536, 537, 538, 540, 541, 542, 544, 546, 547, 549,
550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569,
570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 604, 605, 606, 607, 608, 609, 610,
611, 612, 613, 614, 618, 619, 620, 621, 622, 623, 630, 631, 632, 633, 634, 635, 636, 638, 639, 642,
643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654))
zatímco bych byl radějí za ten
SELECT `id`, `surname`, `firstname`, `company_id`, `email`, `street`, `zip`, `city`, `country_id`
FROM `guest`
WHERE (`id` IN (51, 155, 58, 160, 103, 124, 187, 161, 84, 237, 209, 226, 128, 235, 246, 247, 236,
238, 239, 241, 242, 243, 240, 248, 249, 250, 245, 170, 252, 258, 259, 251, 262, 263, 260, 211, 144,
56, 142, 76, 97, 199, 64, 134, 89, 126, 147, 95, 120, 201, 140, 111, 203, 130, 60, 78, 93, 136, 223,
62, 72, 80, 91, 132, 205, 165, 54, 157, 99, 117, 163, 198, 87, 207, 232, 66, 173, 52, 70, 105, 224,
138, 68, 171, 149, 175, 268, 269, 270, 153, 271, 253, 214, 227, 261, 282, 283, 265, 264, 254, 255,
273, 278, 233, 234, 280, 286, 256, 288, 298, 275, 297, 219, 295, 299, 301, 300, 302, 303, 304, 305,
306, 307, 308, 190, 309, 310, 229, 312, 313, 316, 311, 315, 314, 317, 181, 318, 319, 296, 267, 179,
177, 218, 320, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 185, 244, 279, 281, 230, 257, 231,
276, 335, 291, 292, 337, 338, 339, 342, 343, 336, 351, 284, 350, 346, 345, 349, 285, 347, 228, 289,
354, 355, 340, 322, 348, 290, 352, 353, 294, 293))
kdyby se ale provedl jen jednou :)
- thorewi
- Člen | 84
Jeste se zeptam – bude se to nejak spravovat (v nejblizsi dobe)? Ja totiz ten prvni zpusob pouzivam ve vsech projektech a ptal jsem se ted kolegu a oni teda taky, tak jestli to mame vsude spravovat nebo mame cekat na fix (abychom to nemuseli za par dni zase vsechno vracet zpatky, abychom se vyhli LEFT JOINu)…
Dalsi vec je ta, ze ono totiz ne vsude to jde asi spravit. Pokud vyuzivam NiftyGrid, kde se jako zdroj dat predava Selection, ktery obcas ale nejde uplne vysperkovat, tak pak musim pro kazdy radek volat vlastni Selection, a to pak kdyz mam 100 polozek na stranku, tak misto 2 dotazu (jedno hlavniho a druheho groupnuteho do IN) mam 101 dotazu :/
Diky moc.
- thorewi
- Člen | 84
Tak jeste pripisu k tomuto tematu dalsi vec co jsem objevil protoze to s tim souvisi… Provedl jsem tedy opravu pomoci ->select(…) a mam tento kod:
$reservation_room->related('reservation_room_flag')->select('flag.id, flag.name, flag.suffix');
který mi provedl tento SQL dotaz:
SELECT `reservation_room_flag`.`reservation_room_id`, `flag`.`id`, `flag`.`name`, `flag`.`suffix` FROM `reservation_room_flag` LEFT JOIN `flag` ON `reservation_room_flag`.`flag_id` = `flag`.`id` WHERE (`reservation_room_flag`.`reservation_room_id` IN (389, 390, ...))
SQL dotaz je naprosto spravny, ale pak kdyz jsem to tedy prohnal foreachem, tak mi tam chybeli data. Kdyz ale provedu:
$reservation_room->related('reservation_room_flag')->select('flag.id AS filename, flag.name, flag.suffix')
tak dostanu SQL dotaz:
SELECT `reservation_room_flag`.`reservation_room_id`, `flag`.`id` AS `filename`, `flag`.`name`, `flag`.`suffix` FROM `reservation_room_flag` LEFT JOIN `flag` ON `reservation_room_flag`.`flag_id` = `flag`.`id` WHERE (`reservation_room_flag`.`reservation_room_id` IN (389, 390, ...))
a data mi nechybi… Oba SQL dotazy mi vraci stejny pocet vysledku, takze v nich to nebude – problem tedy bude nekde az pri zpracovani tech vysledku.
- hrach
- Člen | 1838
- S tim selectem jsi nepochopil, co sem chtel. Uvedenim selectu vypnes cache. Nechtel jsem join, ale toto:
{foreach $rooms as $room}
{foreach $room->related('reservation_room') as $reservation_room}
{foreach $reservation_room->related('reservation_room_guest')->select('reservation_room_id') as $rrg
{$rrg->guest->surname}
{/foreach}
{/foreach}
{/foreach}
- nedari se mi nasimulovat, ze by se provadeli ve vicenasobnem related dalsi dotazy, muj testcase:
foreach ($connection->table('author') as $author) {
echo "> $author->id<br>";
foreach ($author->related('book') as $book) {
echo ">> $book->id<br>";
foreach ($book->related('book_tag') as $bookTag) {
echo ">>> $bookTag->tag_id<br>";
echo ">>>> $bookTag->tag->name<br>";
}
}
}
provede korektne jen 4 dotazy.
- michal.lohnisky
- Člen | 64
Vyzkoušeli jsme, ale nic se nezměnilo, stále je zde mnoho selectů typu:
SELECT `id`, `surname`
FROM `guest`
WHERE (`id` IN (51, 155, ...
Používali jsme tento testovací příklad:
{foreach $rooms as $room}
{foreach $room->related('reservation_room') as $reservation_room}
{foreach $reservation_room->related('reservation_room_guest')->where('guest_id IS NOT NULL') as $reservation_room_guest}
{var $guest = $reservation_room_guest->guest}
{$guest->surname}
{/foreach}
{/foreach}
{/foreach}
Přikládám schéma databáze.
- michal.lohnisky
- Člen | 64
Jojo, napadlo mě to, už na to dělám. Ještě pár věcí pozkouším a pak to sem napíšu.
Editoval michal.lohnisky (18. 3. 2013 13:06)
- michal.lohnisky
- Člen | 64
Takže nakonec jsme došli ještě k jednomu zajímavemu zjištění: pokud v databázi promažu data a budu tam mít jen pár záznamů, vše funguje v pořádku; ale když použiješ tuto databázi, tak se generuje těch stejných dotazů více.
Tady máš kód do presenteru:
public function renderDefault(){
$connection = $this->context->database;
foreach ($connection->table('room') as $room) {
echo "> $room->id<br>";
foreach ($room->related('reservation_room') as $reservation_room) {
echo ">> $reservation_room->id<br>";
foreach ($reservation_room->related('reservation_room_guest') as $reservation_room_guest) {
echo ">>> $reservation_room_guest->id<br>";
echo ">>>> {$reservation_room_guest->guest->surname}<br>";
}
}
}
$this->terminate();
}
- hrach
- Člen | 1838
No, je to vcelku logicke porovnani hodnot dvou poli. Alternativou je mozne tam dat sort. Ale to je od 2 radky vic, a asi ne rychlejsi.
- enumag
- Člen | 2118
@hrach: Na tom odkazu co jsi poslal je ještě tahle odpověď. Je tam popsané ve kterých případech bude pravděpodobně rychlejší než array_diff – zda je to případ NDB posuď raději ty.