Diskuze: MySQL Rekurze
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 8 zpráv z 8.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
Samozřejmě, že to je možné. Podívej se na T-SQL. Vytvoříš si proměnnou, ve které budeš mít předka a dokud nebude null, tak pokračuješ v cyklu dále. Při troše snahy ti databáze vyplivne záznamy seřazené tak, jak na sebe navazují.
Zkus pohledat něco ve smyslu "mysql create tree structure query". Něco jsem našel, ale já moc do sql nevidím, ani nemám momentálně možnost to testnout.
V DB to uděláš těžko nebo zbytečně komplikovaně a ničemu si oproti PHP nepomůžeš. Jsou tu na to články, třeba tady: http://www.itnetwork.cz/…tabaze-v-php
Udělat to v PHP samozřejmě není problém, ale nechce se mi zatěžovat
databázi několika dotazy.
Moje metoda v PHP:
public function createLink($id, $link)
{
$data = $this->findOne("SELECT * FROM page WHERE id=:id", ["id" => $id]);
//Pokud existuje,pokračuje v rekurzi jinak začne vracet
if($data)
{
//Přidá aktuální prvek k linku
$link = "/" . $data["url"] . $link;
//Získá postupně vracející se link
$return = $this->createLink($data["section"], $link);
}
else
{
//Vrátí hodnotu linku
return $link;
}
//Vrátí hodnotu linku
return $return;
}
Stačí ti jeden dotaz, poslal jsem ti řešení si to přečti.
Nevidím důvod, proč by měla databáze posílat zbytečně tolik dat.
Kromě režie, potřebné na přenesení takového množství, vzniká i
bezpečnostní riziko, protože skript dostane i informace, které mu nepatří
(například informace o ostatních uživatelích nepotřebuje).
Já se řídím heslem, že by aplikace měla vždy získat přesně ty
informace, které potřebuje, nic navíc, nic míň. A navíc v jendom
dotazu.
Jak jsem psal, řešení je, chce to ale znát trošku víc než SELECT.
Přikládám řešení (včera o půlnoci se mi vážně nechtělo )
Vytvoření tabulky:
DROP TABLE IF EXISTS testtable;
CREATE TABLE IF NOT EXISTS `testtable` (
`Id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Parent` int(11) DEFAULT NULL,
`Url` text
) ENGINE=InnoDB CHARSET=UTF8;
INSERT INTO testtable(Parent,Url) VALUES
(NULL , "/"),
(1 ,"clanky"),
(2 ,"podkategorie"),
(1 ,"obrazky"),
(3 ,"clanek"),
(2 ,"podkategorie");
Vytvoření procedury, která bude data vybírat:
DROP PROCEDURE IF EXISTS CreateTempTable;
DELIMITER $
CREATE PROCEDURE CreateTempTable(IN Param INT) DETERMINISTIC
BEGIN
DECLARE Actual INT;
DECLARE TEMP INT;
SELECT Param INTO Actual;
DROP TABLE IF EXISTS MyTempTable;
CREATE TEMPORARY TABLE MyTempTable(
ID INT NOT NULL,
Prevision INT,
Url TEXT);
WHILE Actual IS NOT NULL DO
INSERT INTO MyTempTable SELECT * FROM testtable WHERE Id=Actual;
SELECT Parent INTO TEMP FROM testtable WHERE Id=Actual;
SELECT TEMP INTO Actual;
END WHILE;
END$
DELIMITER ;
Dotaz je poté jednoduše
CALL CreateTempTable(5);
SELECT * FROM MyTempTable;
nic míň, a dostanu přesně data, které ptořebuji.
5 | 3 | clanek |
3 | 2 | podkategorie |
2 | 1 | clanky |
1 | 0 | NULL |
Používá se TEMPORARY tabulka, takže lze použít všechny příkazy pro třídění, řazení atd. Nejsem si moc jistý, jak to bude fungovat u více uživatelů, ale každá session by měla mít vlastní, takže by v tom problém být neměl.
Snad to na Tebe není moc složité
Zobrazeno 8 zpráv z 8.