tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

jak napsat několikanás. INSERT SELECT jednodušeji?

před 9 lety

Tori
Člen | 32

Zdravím,
nevěděli byste, prosím, jak udělat něco takovéhoto pomocí jednoho dotazu?

$terms = array(
  array('cas'=>..., 'den'=>...),
  array('cas'=>..., 'den'=>...),
  ...
};

INSERT INTO `rezervace` (`id_users`, `id_udalost`, `id_datum`, `id_cas`, `id_termin`) VALUES
    (SELECT 0, $data['id'], d.`id`, c.`id`
            FROM `cas` c, `datum` d
            WHERE c.`hodina` = $terms[0]['cas'] and d.`den` = $terms[0]['den']),
    (SELECT 0, $data['id'], d.`id`, c.`id`
            FROM `cas` c, `datum` d
            WHERE c.`hodina` = $terms[1]['cas'] and d.`den` = $terms[1]['den']),
    ......

Našla jsem sice toto řešení, které bych snad dala dohromady, ale připadá mi dost nepřehledné.
Jde o to, že se ten dotaz zopakuje cca 20–100× pro různé (i opakující se) kombinace dne a hodiny. Datumy i časy jsou v samostatných tabulkách, nejdřív uložím všechny možné časy a datumy (INSERT IGNORE), a pak jsem pro každou kombinaci spouštěla jednoduchý INSERT .. SELECT. Šlo by automaticky vytvořit několikanás. INSERT, kde by se pro každý řádek měnily hodnoty v SELECTu?

Ale možná je chyba v logice zpracování.

Editoval Tori (5. 1. 2011 12:07)

před 9 lety

Milo
Nette Core | 1119

Ta struktura mi přijde šílená…

Nebylo by snažší, selectnout si všechna ID casu a datumu pak vytvorit pole v multivalues? Záleží, kolik záznamů v těch tabulkách a v $terms máš.

$values = array(
   'id_users'   => array(),
   'id_udalost' => array(),
   'cas'        => array(),
   'den'        => array(),
);

$casy = dibi::query( "SELECT [id], [hodina] FROM [casy]" )->fetchPairs('hodina','id');
$dny  = dibi::query( "SELECT [id], [den]    FROM [dny]"  )->fetchPairs('den',   'id');

foreach( $terms AS $term )
{
    $values['id_users'][]   = 0;
    $values['id_udalost'][] = $data['id'];
    $values['id_datum'][]   = isset( $dny[  $term['den'] ] ) ? $term['den'] : NULL;
    $values['id_cas'][]     = isset( $casy[ $term['cas'] ] ) ? $term['cas'] : NULL;
}

dibi::query( "INSERT INTO [rezervece] %m", $values );

Celé to ještě uzavřit do transakce. Ale je to šílenost.

před 9 lety

Tori
Člen | 32

Milo:
No ano, je to šílenost.
Pro představu – jde o systém na zapisování se na konzultace/zkoušky apod., elektronická verze papíru na dveřích od kabinetu. Lektor vypíše 1+ termínů (= konkrétní den, od-do) ke každé „události“ a zadá délku jednotlivých políček rozpisu („rezervací“). Na každý čas se může přihlásit 1+ studentů, ale každý student si smí rezervovat pouze jeden čas v rámci jedné události.

Takže když např.lektor vypíše jen dva termíny, stejný den po 2 hodinách ráno a v poledne, do DB jdou data asi ve tvaru:

id_události | id_termínu | datum    | začátek | id_studenta
------------------------------------------------------------
      1     |     1      | 5.1.2011 |  08:00  |     0      |    * neuvedené hodnoty se opakují
      *     |            |          |  08:20  |     0      |
            |            |          |  08:40  |     0      |
            |            |          |  09:00  |     0      |
            |            |          |  09:20  |     0      |
            |            |          |  09:40  |     0      |
            |     2      | 5.1.2011 |  12:00  |     0      |
            |            |          |  12:20  |     0      |
            |            |          |  12:40  |     0      |
            |            |          |  13:00  |     0      |
            |            |          |  13:20  |     0      |
            |            |          |  13:40  |     0      |
------------------------------------------------------------

Samozřejmě, kdybych ukládala přímo ty časy a datumy, ušetřím si sice práci při vytvoření/editaci termínů, ale za cenu značné redundance – proto jsem je vystrčila do samostat.tabulek. Na druhou stranu není pravděpodobné, že by někdo mohl chtít editovat jeden časový údaj v celé DB, třeba změnit všechny „08:00“ na „nekřesťanská hodina“.

Takže: radil byste v tomto případě ukládat datumy a časy přímo do tabulky rezervace, místo blbnutí s FK a dvěma extra tabulkami, anebo ještě něco jiného?
Každopádně díky moc za ochotu :)

před 9 lety

Milo
Nette Core | 1119

Hned je jasnější, k čemu to je.

Strukturu bych odvíjel od toho, kolik událostí a termínů v databázi celkem bude, zda to bude využívat více pedagogů, jestli mají termíny událostí nějak pevně dané začátky a délku trvání, zda se mohou překrývat, jaká je pravděpodobnost, že se budou měnit, atd…

Pokud by struktura měla nahradit jeden list papíru na dveřích jednoho učitele kdy na daných 20 minut může přijít jeden student, udělal bych to asi následovně:

STUDENT (PRIMARY id)

id jmeno
1 Pepa
2 Petra

UDALOST (PRIMARY id)

id nazev
1 Konzultace predmet 1
2 Konzultace 2

TERMIN (PRIMARY id – asi zbytecne; UNIQUE idUdalost, idStudent; UNIQUE idUdalost, cas)

id idUdalost cas idStudent
1 1 5.1.2011 08:00 1
2 1 5.1.2011 08:20 NULL
3 1 5.1.2011 08:40 2
4 1 5.1.2011 09:00 NULL
5 1 5.1.2011 12:00 NULL
6 1 5.1.2011 12:20 NULL
7 1 5.1.2011 12:40 NULL
8 1 5.1.2011 13:00 NULL

Editoval Milo (6. 1. 2011 0:16)

před 9 lety

Tori
Člen | 32

Milo:
Díky moc. Měla jsem opravdu špatně navrhnutou db.