Autor | Zpráva | ||
---|---|---|---|
houbín Profil |
Zdravím.
Mám takovouto tabulku: datum | cas | teplota | vlhkost | vitr | srazky | oblacnost Potřebuji vypsat max a min u teploty, max vítr a max srážky. Budou tedy 4 výsledky a ke každému bych chtěl ještě přidat datum. Zkoušel jsem různé příkazy, ale nedošel jsem na to, jak přiřadit k výsledku agregační funkce ještě datum. Mohl bych udělat čtyři samostatné příkazy, ale připadá mi to nevhodné. Pro jeden záznam jsem vymyslel tento jednoduchý příkaz, ale jak do toho narvat ještě MIN(teplota), atd. nevím. SELECT MAX(teplota), datum FROM tabulka |
||
juriad Profil |
Použij 4 dotazy. Ten dotaz, který jsi napsal totiž ani nevrací to, co bys čekal; správně je to:
SELECT t1.* FROM tabulka t1 JOIN ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 ON t1.teplota = t3.teplota; Pozor, toto vrátí všechny řádky s nejvyšší teplotou. Pokud bys chtěl jen ten nejnovější: SELECT date(max(timestamp(t1.datum, t1.cas))) AS datum, time(max(timestamp(t1.datum, t1.cas))) AS cas, t1.teplota FROM tabulka t1 JOIN ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 ON t1.teplota = t3.teplota; Pokud chceš informace o vlhkosti, atp. pro nejvyšší teplotu, musíš přidat další úroveň: SELECT t0.* FROM tabulka t0 JOIN ( SELECT max(timestamp(t1.datum, t1.cas)) AS dt, t1.teplota FROM tabulka t1 JOIN ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 ON t1.teplota = t3.teplota; ) t4 ON t0.teplota = t4.teplota AND timestamp(t0.datum, t0.cas) = t4.dt Mimochodem, máš nějaký důvod použít místo jednoho sloupce typu DATETIME dva sloupce typů DATE a TIME? Zbytečně se tím komplikuje ten dotaz. (Viz zvýrazněné části.) |
||
houbín Profil |
Měření se provádí v rámci možností jen 2x denně (každý den ve stejné časy), takže sloupec 'cas' obsahuje pouze hodnoty 1, nebo 2.
Děkuji za radu. Zjistil jsem, že SQL rozumím méně, než jsem myslel. Možná jsem se nevyjádřil správně, nebo nerozumím řešení. Pomocí JOIN spojím přece více tabulek. Já mám však jen jednu tabulku, kde jednotlivé atributy jsou 'teplota', atd., jak jsem psal v předchozím příspěvku. Moje myšlenka, proč raději vymyslet jeden příkaz místo čtyř samostatných, byla taková, že bych zbytečně zatěžoval (teoreticky) server. Za 2 roky bude v databázi přibližně 15–20 tis. záznamů, takže se snažím myslet dopředu. Údaje, které chci vypsat, budou vedeny jako rekordy od počátku měření. EDIT: snad jsem to nějak pochopil, SQL vrací přesně to, co potřebuji, děkuji. takové použití JOINu by mě nenapadlo. |
||
juriad Profil |
Prosím tě, zbav se toho sloupce cas; je úplná blbost ukládat tam číslo 1 nebo 2. Až se za rok rozhodneš, že chceš měřit častěji, budeš přepisovat všechny skripty, aby ukazovaly správný čas?
Navrhuji sloupce datum a cas sloučit do jednoho, asi bych mu ponechal název datum a byl by typu DATETIME. Z tohoto sloupce můžeš vždy zjistit datum i čas zvlášť. A z času můžeš zjistit, zda to bylo dopoledne nebo odpoledne. Jedině, pokud bys chtěl zpracovávat dopoledne a odpoledne úplně zvlášť, tak by se to vyplatilo rozlišit zvláštním sloupcem. Ano, máš jen jednu tabulku, ale já v tom dotazu propojuju tabulku s výsledkem nějakého poddotazu. SELECT max(t2.teplota) teplota FROM tabulka t2 ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 SELECT t1.* FROM tabulka t1 JOIN ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 ON t1.teplota = t3.teplota; ( SELECT max(timestamp(t1.datum, t1.cas)) AS dt, t1.teplota FROM tabulka t1 JOIN ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 ON t1.teplota = t3.teplota; ) t4 SELECT t0.* FROM tabulka t0 JOIN ( SELECT max(timestamp(t1.datum, t1.cas)) AS dt, t1.teplota FROM tabulka t1 JOIN ( SELECT max(t2.teplota) teplota FROM tabulka t2 ) t3 ON t1.teplota = t3.teplota; ) t4 ON t0.teplota = t4.teplota AND timestamp(t0.datum, t0.cas) = t4.dt Záleží, o jaké záznamy máš zájem z databáze. Pokud by tě vždy zajímala jen extrémní hodnota a datetime, kdy naposledy nastala, a nic jiného, tak by to šlo malinko zkrátit na úroveň 3. dotazu (s ORDER BY dt DESC LIMIT 1 ).
Jelikož dotazy na teploty, vítr a srážky vrací stejné údaje, můžeš je vytáhnout z databáze UNIONem. Ale to je spíš jen mikrooptimalizace, kterou bych si zpočátku i odpustil. |
||
TomášK Profil |
#5 · Zasláno: 7. 4. 2016, 01:26:36
Předpokládám, že pro každý čas je jen jedno měření. Pak ten dotaz jde zkrátit na
SELECT datum, cas, teplota FROM tabulka ORDER BY teplota DESC, datum DESC, cas DESC LIMIT 1 JOIN je potřeba, pokud by vás zajímaly všechny záznamy, kdy bylo dosaženo maxima, nejen poslední. Čtyři dotazy jsou správné řešení. Zátěž serveru pro 15-20 tisíc je nezajímavá, je to tak málo, že se tím nemusíte zabývat. S vhodnými indexy ty čtyři dotazy budou během pár ms. |
||
houbín Profil |
#6 · Zasláno: 7. 4. 2016, 18:00:22
Děkuji za rady. Nakonec jsem využil návrhu od TomášK. Nevím, proč mě to nenapadlo! Někdy člověk přemýšlí příliš složitě :D
|
||
Časová prodleva: 9 let
|
0