Diskuze: Složitejší SQL select
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 14 zpráv z 14.
//= 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.
Ahoj, neumím SQL pořádně, takže je ten dotaz asi blbě, ale snad z toho pochopíš princip
SELECT DISTINCT devID FROM (
SELECT DISTINCT devID FROM itn one WHERE transfer = 1 ORDER BY date DESC
UNION
SELECT DISTINCT devID FROM itn zero WHERE transfer = 0 ORDER BY date DESC
) dohromady WHERE transfer = 1 ORDER BY date DESC
Kdybys to z toho nepochopil, tak rozepíšu postup.
Pak sem prosím napiš správný dotaz.
V kroku 2 dostaneš tabulku, ve které jsou jen nejaktuálnější záznamy o
předání zaměstnanci.
V kroku 3 dostaneš tabulku, ve které jsou jen nejaktuálnější záznamy o
vrácení zařízení.
V kroku 4 je spojíš a dostaneš nejaktuálnější záznam o zařízení. Z toho vybereš jen ty, které má zaměstnanec u sebe.
Ahoj, zkoušel jsem, ale nepodařilo se mě to sestavit. Ten dotaz v závorce mě samotný fungoval, ale když jsem to dal do toho kompletního dotazu, tak to hazelo chybu. No ale hledal jsem hledal a našel jsem jiný způsob. Mrkněte na níže uvedený dotaz, zdá se, že to funguje tak jak potřebuju, ale můžu narazit na jiné problémy.
select * from #table as list1
where not exists (select id from #table as list2 where list2.devID = list1.devID AND list2.date > list1.date) AND transfer = 1
Potřebuješ získat kombinaci <devId, empId>, kde transfer = 1 a
neexistuje stejná kombinace s vyšším datem, kde transfer = 0.
Následující select řeší i to, kdyby stejné zařízení stejným
zaměstnancem bylo půjčené i vrácené ve stejný den:
SELECT
vypujcka.*
FROM
EvidenceZarizeni AS vypujcka
LEFT OUTER JOIN EvidenceZarizeni AS vratka ON
vratka.transfer = 0
AND
vratka.devID = vypujcka.devID
AND
vratka.empID = vypujcka.empID
AND
vratka.date >= vypujcka.date
WHERE
vypujcka.transfer = 1
AND
vratka.ID IS NULL
;
Pokud potřebuješ např. jen seznam aktuálně půjčených zařízení, lze select upravit (např. SELECT DISTINCT vypujcka.devID ...)
Neuvádíš jaká je to DB, tento select je pro MS SQL.
Problém by byl, kdyby zaměstnanec zařízení vrátil a pak ve stejný den
znovu půjčil.
To by šlo řešit např. tím, že číslo protokolu nové výpůjčky by
pravděpodobně bylo vyšší než číslo protokolu vrácení.
BTW tabulka nesplňuje 2. NF - atributy transfer, date jsou závislé na atributu protocol.
Ahoj
podľa mna mas tu tabulku navrhnutu zle. prve udaje empid a zamid zapisujes
zbytocne lebo zamestnanec si nemoze pozicat 2x nieco co este nevratil, naviac z
tohto navrhu nie je jasne co tabulka reprezentuje. DB tabulka by mala
zohladnovat ucel na co ju potrebujes v tomto pripade evidencia pozicania a
vratenia. stlpce
id
devid
empid
zo zadania je zrejme ze pri pozicani su rozne protokoly 133 134, ale nie je
zrejme ci existuje viac protokolov vratenia ( vratene bez poskodenia, vratene
poskodene, vratene po termine atd...)
budem predpokladat ze protokol ako predania tak odovzdania moze mat viac
stavov.
ja by som si tabulku navrhol takto:
id
devid
empid
protocol_pozicania
date_pocicania
protocol_vratenia
date_vratenia
riadok kde nie su vyplnene udaje o vrateni(hodnoty su null) je zariadenie stale pozicane. pri vrateni len dopises datum a typ protocolu.
SELECT * FROM evidence WHERE date_vratenia IS NULL
potom jednoduchym selectom vies zistit ci zamestnanec uz dane zariadene pozicane ma, atd. atd.
neviem ci uz nie je neskoro tento moj komentar, ale myslim ze tato jednoducha zmena struktury v jednej tabulke ti dost ulahci zivot.
Tak jen doplním, že se jedná o půjčování HW, db je MS SQL a není
možné, aby se jedno devID půjčilo dvakrát. Jinak původně jsem měl v
tabulce ještě další dva sloupce s datum_vrácení a stav_vrácení. Ale na
radu jednoho programátora, který mě řekl, že pokud tam mám stav(transfér)
tak je jasný, jestli se jedná o datum půjčení nebo vrácení a stejně tak
u toho stavu. Tak jsem ty sloubce odstranil, to jsem ale nevěděl co mě čeká
Když jsem je tam měl, tak
jsem si to selektoval jak píšeš a fungovalo mě to spolehlivě.
K tomu číslu protokolu, když má někdo půjčený třeba notebook, monitor,
telefon, batoh, tak nemusí vrátit vše současně, ale jen něco. Číslo
protokolu mě značí, které zařízení je součástí vracení. například
pokud bude vracet notebook a telefon, přibudou do tabulky dva řádky se
stejným číslem protokolu. To co uvádíš, na protokolu 133 si
zaměstnanec(118) převzal zařízení 53, 96, 132 a pak druhý den na dalším
protokolu 134 si převzal zařízení číslo 368, které zase vrací na
protokolu 216 plus ostatní zařízení.
Asi bych to řešil vytvořením více tabulek.
ve vazební tabulce by bylo ID_HW, ID_User, Datum_půjčení,
Datum_Vrácení
při půjčení vytvoříš ve vazební tabulce nový záznam, při vrácení
jen záznam doplníš o datum vrácení...
Případně bych dal do tabulky HW nějaký "bool" sloupec, kde by bylo uvedeno
jestli je HW k dispozici, nebo je půjčeno (true/false)
Chybí tam ty protokoly. Když už by se měla měnit struktura, tak:
Místo Datum_půjčení, Datum_Vrácení bude protocolPredani, protocolVraceni
(u dosud nevrácených zařízení bude NULL)
Protokol bude mít atributy empID, date, transfer (1 = předání, 0 =
vrácení)
Dále tam bude seznam zařízení na protokolu s atributy protocol, devID
(snažím se zachovat použité názvy)
Pokud nutně nepotřebuje evidovat souhrnně půjčování a vracení, ale stačí mu evidovat výpůjčky jednotlivých HW, pak jsou ty protokoly zbytečné...
SELECT
predane.devID
,predane.empID
,predane.pocet - ISNULL(vratene.pocet, 0) stav
FROM (SELECT
devID
,empID
,COUNT() pocet
FROM [Dusik].[dbo].[tabulka1]
WHERE transfer = 1
GROUP BY devID
,empID) AS predane
LEFT JOIN (SELECT
devID
,empID
,COUNT() pocet
FROM [Dusik].[dbo].[tabulka1]
WHERE transfer = 0
GROUP BY devID
,empID) vratene
ON predane.devID = vratene.devID
AND predane.empID = vratene.empID
WHERE predane.pocet - ISNULL(vratene.pocet, 0) <> 0
Ty dve nebo tri tabulky jsou lepsi. Uz jen proto, ze muzes vytvorit historii pujcovani. Ktere zarizeni bylo kolikrat pujceny. Nebo i stav, do kdy ma byt pujcene, nebo jak dlouho blo pujcene. A u tabulky zarizeni pak muzes evidovat, jake je k disposici, nebo historii udrzby. Samozrejme zalezi na tom jak az moc to chces mit prehledny. Ale vetsi prehlednost je vzdy lepsi. Ikdyz ji treba zatim nevyuzijes.
Zobrazeno 14 zpráv z 14.