Diskuze: SQL dotaz přes více tabulek
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Tvůrce

Zobrazeno 11 zpráv z 11.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.
Já bych to udělal třeba takhle:
SELECT * FROM `destinations`
WHERE destinations.status = 'allow'
AND EXISTS (SELECT 1 FROM `slope` AS s WHERE s.destination_id = destinations.id AND s.slope_type_id = 4)
AND EXISTS (SELECT 1 FROM `slope` AS s WHERE s.destination_id = destinations.id AND s.length >= 1500)
Vsechny drahy, ktere splnuji podminku. Primarni tabulka, jsou drahy. K nim
chces pridat dalsi udaje.
areal (id_areal, nazev)
draha (id_draha, id_areal, nazev, delka, obtiznost)
SELECT
a.nazev AS draha,
b.nazev AS areal,
a.delka
FROM
draha a
LEFT JOIN areal b ON b.id_areal=a.id_areal
WHERE
a.delka > 15
AND a.obtiznost > 4
Alespon jedna podminka
a.delka > 15
OR a.obtiznost > 4
A pokud te zajima pouze jmeno arealu, tak se da pouzit DISTINCT k odfiltrovani duplicit, ale v SELECTU musis mit jen jmeno arealu, b.nazev. Priklady zapisu se daji najit googlem...
SELECT DISTINCT SalesTerritoryCountry
FROM [AdventureWorksDW2012].[dbo].[DimSalesTerritory]
ORDER BY SalesTerritoryCountry
Jeste kombinace s tim allow. To si snadno prepises do vlastniho, ale ty zavorky jsou dulezite.
b.povoleno = 1
AND (a.delka > 15 OR a.obtiznost > 4)
A když později budu upravovat ještě i že se dá filtrovat jiný parametr areálu, typicky jaký tam je vlek, tedy podobné kritéria jako pro dráhu.. To už budou vlastně dvě stejný věci který bych potřeboval jako primární tabulku, ale zároveň propojenou a jen v jednom dotazu. .:(
Pozn. Mozna by bylo dobre uz na zacatku rici, ze se jedna o horsky areal s lyzarskou drahou, vlekem. Pro lepsi predstavu.
Nechapu otazku. Do toho sql dotazu muzes stale doplnovat. Tam je hlavne
dulezite napsat spravne podminku.
Se na to divas obracene, mozna.
Ty mas arealy, ktere maji vleky a drahy. Drahy jsou ruzne obtizne, ruzne dlouhe.
Nechapu, Areal nebo draha je povolena, nebo oboji. Budu uvazovat oboji.
Takze, tebe zajima:
No, a presne takto stavis sql dotaz
SELECT ... FROM drahy LEFT JOIN areal -- vyber drahy, pripoj k nim info o arealu
WHERE
drahy.povoleno = true AND
areal.povoleno = true AND
(drahy.delka>15 AND drahy.obtiznost<4 AND drahy.vlek=true) -- vsude AND, zavorka nemusi byt
Nebo chces, aby platili nektere parametry spolecne...
((drahy.delka>15 OR drahy.obtiznost<4) AND drahy.vlek=true) -- u OR zavorku mit musis
Pouzivani and, or, je 1. hodina programovani, boolenovska algebra, stredni, mozna uz zakladni skola, vs take. Pripadne se to uci jeste v matematice, stredni skola, vs take. To jsou takove ty silene podminky "Kdyz prsi, tak se neco vykona". Soucasne jsou to v programovani podminky IF (a==b and c==d).
Vysledkem dotazu je seznam drah. Treba 3 radky. Co s tim dal chces provest, je na tobe.
Muzes udelat jen SELECT DISTINCT areal.id FROM ... a cele to uzavrit do dalsiho selectu, kde k arealu pripojis dalsi info. Nebo areal.id vyuzijes pro vytahnuti vsech drah arealu. Nejen tech, ktere vyhovuji podmince.
SELECT a.id, a.name, b.name
FROM drahy a ON ...
LEFT JOIN areal b ON ...
WHERE b.id IN (SELECT DISTINCT areal.id FROM ...)
ORDER BY ...
Vyber vsechny drahy, ktere maji areal.id z tabulky sql dotazu v zavorce.
Nebude to trvat dlouho, protoze si vysledek dotazu v zavorce ulozi do
pameti.
Pokud bys tu zavorku pouzil do FROM, tak je nutne dat te zavorce alias. Aby s ni
slo pracovat. Ono, i sql bude psat error.
SELECT** x.id** ...
FROM (SELECT DISTINCT areal.id FROM ...) **x**
LEFT JOIN drahy z ON z.id_areal = **x.id_areal
**WHERE ...
Úplně přesně nechápu problém, ale třeba ti moje rada dokáže pomoct a rozšířit možnosti řešení daného problému. V případě že si potřebuješ dotáhnout data na příč tabulkám a podle toho pak dále s tím pracovat, nebo se může jednat o tu samou tabulku, ale není možné to vytáhnout v jednom dotaze, tak doporučím.
V selektu můžeš udělat již hotový dotaz a vytáhnout si do něj údaj jaký chceš, samozřejmě se musí jednat o jeden výsledek s jedním parametrem dle mnou uvedeného příkladu. Těch selektů můžeš udělat kolik chceš i v rámci stejné tabulky. Tak snad se ti to bude hodit. Někdy to ušetří spoustu času.
SELECT d.*, (SELECT s.destination_id FROM slope s WHERE neco AND neco) AS nove_id FROM destinations d WHERE nove_id =1234;
A napsal jsem to špatně. Na konci nemůžeš udělat nove_id = 1234, ale již " WHERE d.neco = nove_id". Chtěl jsem to uvést jako příklad a nepřemýšlel již u toho.
Ano, poprvé jsem to nenapsal úplně přesně.. Nicméně ať zkouším různě kombinace a přidávám nějaké SQL podmínky, tak furt nemám kýžený výsledek..
Jde o to, že mám dejme tomu 200 areálů, každý má třeba v rozmezí 2-15 nějakých drah (jedna je 1000m dlouhá a nejlehčí, další 785m dlouhá a obtížně nejtěžší atd..)..
Do filtru zadám, že chci dráhy delší jak 1000m a středně těžký.. Jenže když udělám dotaz s ANDy, tak to hledá JEN dráhy, které splňují oba požadavky.. Avšak já chci najít ty areály, které mají alespoň jednu dráhu delší jak 1000m (ale může mít jinou obtížnost) a aspoň jednu, co má střední obtížnost (ale délka může být nižší jak 1000m)..
Když tam dám ORy, tak to ale potom najde areály, které některou podmínku nesplňují - třeba jim chybí obtížnost správná.. Další věcí co možná jsem zapomněl říct nebo to nevyznělo správně je ta, že filtrovat se dá podle více obtížností zároveň, zadám si třeba dvě, takže chci výsledný areál, který má obě obtížnosti a ještě alespoň jednu dráhu delší než 1000m
Ani DISTINCT mi nepomohl
Tak jsem to nakonec nějak namastil a zdá se funkčně. Trochu víc jsem
pogooglil a nakonec jsem dotaz doplnil o tento kus podmínky a funguje to
AND EXISTS (SELECT 1 FROM slope s WHERE s.destination_id = d.id AND s.slope_type_id = 4)
takže se mi dostane toho, že všechny požadované typy obtížnosti které
jsou vybrány
Díky všem co poradili
drahy obtiznosti 1 nebo 3 nebo delky 1000
obtiznost IN (1,3) OR delka>1000
obtiznost=1 OR obtiznost=3 OR delka>1000
drahy obtiznosti 1 nebo 3 a soucasne delky 1000
obtiznost IN (1,3) AND delka>1000
(obtiznost=1 OR obtiznost=3) AND delka>1000
obtiznost=1 AND delka>1000 OR obtiznost=3 AND delka>1000
(obtiznost=1 AND delka>1000) OR (obtiznost=3 AND delka>1000)
drahy obtiznosti 1 a 3 a soucasne delky 1000
obtiznost IN (1,3) AND delka>1000
(obtiznost=1 OR obtiznost=3) AND delka>1000
delší jak 1000m a středně těžký (rekneme 3 je stredne tezka)
obtiznost IN (3) AND delka>1000
obtiznost=3 AND delka>1000
Pokud mas vic filtru, tak bych sel do zavorkoveho reseni
(delka>2000) OR (obtiznost=1 AND delka<100)
Chci s delkou 2000 (pro dospele bezky nebo sjezd) a soucasne obtiznost 1 s delkou<100 (pro deti). Ted by to porovnalo parametry drahy a zda vyhovuje aspon jedne zavorce, tak ji prida do vystupu
Ten DISTINCT dela to, ze odfiltruje duplicity. Kdyz pouzijes ten muj sql dotaz, do podminek WHERE das drahy, ale v SELECT budes mit jen jmeno arealu, tak, kdyz ma areal 5 drah, 3 vyhovuji, tak by tam byl areal 3x.
SELECT arealy.name
FROM drahy LEFT JOIN arealy ON drahy.id_areal=arealy.id_atealy
WHERE (drahy.delka>2000) OR (drahy.obtiznost=1 AND drahy.delka<100)
Tady to ti vrati treba 5x stejny areal, ale kdyz to zmenis na SELECT DISTINCT , tak by to melo dat jen jeden areal.
Zobrazeno 11 zpráv z 11.