Igen valami ilyesmiel próbálkoztam de sehogy se akar összejönni:
select * from
(SELECT id, COUNT(*)
FROM items
GROUP BY id
HAVING COUNT(*) = 1)
WHERE type='477' and status='OPEN';
Igen valami ilyesmiel próbálkoztam de sehogy se akar összejönni:
select * from
(SELECT id, COUNT(*)
FROM items
GROUP BY id
HAVING COUNT(*) = 1)
WHERE type='477' and status='OPEN';
A belső selected jó (leválogattad a kérdéses ID-jű sorokat), de ehhez újra hozzá kell joinolnod az items táblát, hogy vizsgálni tudd a type és status-t.
Ilyenkor mennyire elegáns lenne db fiddle példa...
Én kérek elnézést!
javaslom, hogy változtasd meg a kérdésedet.
annak, hogy leválogatsz egy táblát, majd megint leválogatod, nem sok értelme van.
miért nem szeded le az items táblából azokat a tételeket, amiknél egyszerre teljesül minden feltétel?
Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis
SELECT *
FROM items
INNER JOIN
(
SELECT id
FROM items
WHERE type='477' and status='OPEN'
GROUP BY id
HAVING COUNT(*) = 1)
) itemcount on items.id=itemcount.id
"Debugging is like being the detective in a crime movie where you're also the murderer."
select id, min(status) status, min(type) type
from items group by id
having count(*)= 1 and min(status) = 'open' and min(type) = 477;
ez nem jó, mert ha egy id csoporton belül a min(status) az nem open, vagy a min(type) az nem 477, akkor nem ad helyes választ.
Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis
...javítva:
SELECT *
FROM items
INNER JOIN
(
SELECT id
FROM items
WHERE type='477' and status='OPEN'
GROUP BY id
HAVING COUNT(*) = 1
) itemcount on items.id=itemcount.id
"Debugging is like being the detective in a crime movie where you're also the murderer."
Ennek fuss neki mégegyszer.
Ispy kódja az, ami továbbra sem jó.
[ Szerkesztve ]
Mi a baj vele?
"Debugging is like being the detective in a crime movie where you're also the murderer."
A kérdés az volt, hogy azok a sorok kellenek amelyek ID-ja csak egyszer szerepel a táblában, továbbá igaz rájuk, hogy status = open, type = 477.
Nálad a status = open, type = 477 szűrés az aggregráció előtt történik, mert az a WHERE-ben van, nem a HAVING-ben.
Emiatt ha pl. így néz ki a tábla, akkor az eredményedbe mindkettő sor bekerül:
id | status | type
--------|--------|------
1 | open | 477
1 | closed | 476
Erre nem teljesül az, hogy az ID csak egyszer szerepel, hiszen 2 sorban is ott van, és mivel csak az ID alapján történik a self join, visszadja az ID-hoz tartozó összes többi sort is, amelyekre a status = open, type = 477 nem teljesül.
A min(status) meg min(type) részhez annyi, hogy a having count(*) miatt eleve csak az 1 tagú csoportokat vizsgáljuk, ahova mindegy, hogy min vagy max vagy más csoport függvényt írok, de valamit muszáj, hogy megegye az aggregráció + having. A havingben ott van utána még a számunkra szükséges szűrés, ez az aggregáció után történik, és az 1 elemű csoportokból csak a nekünk szükségeseket hagyja meg.
Szerintem a kérdés direkt van ilyen egyszerűre fogalmazva, hogy meg lehessen oldani subquery meg analitikus függvény nélkül.
[ Szerkesztve ]
ja, akkor tessék:
SELECT *
FROM items
INNER JOIN
(
SELECT id
FROM items
GROUP BY id
HAVING COUNT(*) = 1
) itemcount on items.id=itemcount.id
WHERE items.type='477' and items.status='OPEN'
"Debugging is like being the detective in a crime movie where you're also the murderer."
Akár alselectet is lehetett volna írni:
SELECT *
FROM items
WHERE type=477
AND status='OPEN'
AND id in (SELECT id
FROM items
GROUP BY id
HAVING COUNT(*) = 1)
Elvileg ez ekvivalens az előző, joinolt megoldással.
#4660: Szerintem a kérdés direkt van ilyen egyszerűre fogalmazva, hogy meg lehessen oldani subquery meg analitikus függvény nélkül.
Szerintem meg észre kéne venni, hogy ez a feladat két lépésből áll, először leválogatni az egyelemű tételeket, majd azokon szűrni.
Ha egy selectben szűrsz és számolsz, akkor fals eredményt fogsz kapni, mivel a szűrt eredményhalmazt fogja megszámolni, nem a teljes táblát.
(Először a WHERE értékelődik ki, és csak utána a HAVING)
-> vagy alselect vagy join kell.
[ Szerkesztve ]
Hello IT! Have you tried turning it off and on again?
törölve.
[ Szerkesztve ]
Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis
Sziasztok!
A segítségeteket szeretném kérni (Oracle PL/SQL).
Van egy tábla (DATUMOK) az alábbi oszlopokkal:
ID
DATUM
Azt szeretném lekérdezni, hogy mely rekordoknál fordul az elő, hogy kisebb ID-val, de nagyobb DATUM értékkel szerepel, mint egy másik.
Példa:ID DATUM
100 2020-01-01
200 2019-06-30
Hogyan lehetséges ezt lekérdezni, hogy ne szemmel veréssel kelljen összehasonlítgatni, vannak e ilyen sorok a táblában és melyek?
Köszönöm!
[ Szerkesztve ]
“Mankind invented the atomic bomb, but no mouse would ever construct a mousetrap.” Albert Einstein
valahogy így:select t1.*,t2.* from datumok t1, datumok t2 where t1.id>t2.id and t1.datum<t2.datum
fejből írtam, nem biztos, hogy szintaktikailag helyes.
Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis
Analitikus függvényekkel is neki lehet esni és akkor nem kell descartes szorzat:WITH src AS (
SELECT
id
, datum
, LEAD(id) OVER ( ORDER BY ID ) next_id
, LEAD(datum) OVER ( ORDER BY ID ) next_datum
FROM datumok)
SELECT *
FROM src
WHERE datum > next_datum
Mit csinál a LEAD és az OVER?
A LEAD függvénnyel olyan oszlop hozható létre, ami egy meglévő mező csoportosított/sorbarendezett értékeit eltolja.
tm5 megoldásában a halmaz nincs csoportosítva, csak ID alapján sorbarendezve. E szerint az ID és a DATUM mezőket egy rekorddal eltolva képzi meg a next_id és next_datum oszlopokat.
Alapértelmezettként az eltolás mértéke 1, ekkor elhagyható.
A LEAD-hez hasonló még a LAG függvény, ahol az eltolás "ellenkező" irányba történik.
Köszi Apollo! Fantasztikus ez az Oracle.
És tm5 azért csomagolta egy WITH-be, mert WHERE mögött ezek az analitikus cuccok nem használhatók, csak projekcióban (vagy hogy is hívják a from előtti részt)?
A next_id kiszámításának van valami különleges oka, vagy az amúgy elhagyható? Én feleslegesnek érzem az aktuális probléma szempontjából. Hacsak az oracle belső mechanizmusai ezt mégis megkövetelik valami mágikus okból.
Ez a megoldás amúgy a Descartes szorzathoz képest milyen előnyöket nyújt? Gyorsabb? Kíméli a memóriát? Elegánsabb?
A paraszti eszem azt súgja, hogy nem igazán lehet gyorsabb, hiszen ígyis úgyis kétszer szelektál a táblából, csak más sorrendben teszi a folyamat során. Hacsaknem attól ér el gyorsabb működést, hogy a nyers adatok diszken való rendezettségének köszönhetően a vinyó kevesebb fejmozgással is végre tudja hajtani a lekérdezést egy nagy adathalmazon. Bááár, azzal, hogy az eredeti halmazon nincs orderby, a lead függvény meg sorrendezett halmazon operál, még ez sem feltétlenül biztos. Asszem elkalandoztam.
szerintem ez a megoldás nem a kérdésre ad választ, mert ez csak azt mondja meg, ha két egymásutáni rekordnál rossz a dátum sorrendje, azt nem, hogy két tetszőleges rekordnál is az.
tehát ha van egy id=300, datum='2019-07-30' rekordod, azt a te megoldásod nem találja meg, az enyém igen. a kérdés, hogy a kérdező mit akart kérdezni
Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis
Hát a lenti feladatleírás alapján ha az ID nő akkor a DATUMnak is növekvőnek kell lennie.
Tehát ha ID1 < ID2 < ID3 < ID4 < ID5... akkor DATUM1 < DATUM2 < DATUM3 < DATUM4 < DATUM5... az elvárt állapot. Ezek alapján szerintem fölösleges a DATUM5-t mondjuk a DATUM2-vel hasonlítani, elég csak DATUM4-gyel, mert nem hiszem, hogy van olyan eset, hogy kisebb lenne DATUM2-nél de nagyobb mint DATUM4.
Szóval igen, ez csak egymás utáni párokat vizsgál, de szerintem ez elég.
Szmeby:
Én szeretem használni a WITH-et, mert jobban elszeparálja az egyes logikákat egymástól. Jelen esetben akkor a teljes LEAD-es részt bele kellett volna tenni a WHERE-be is, mert ugye ugyanazon queryn belül nem tudod a SELECT-ben megadott aliasokat a WHERE feltételben használni. Szóval így szebb és érthetőbb.
A next_id azért kellett, mert így látod, hogy melyik két egymást követ ID-nál van gond a dátumokkal. De elhagyható...
Szerintem ez jóval gyorsabb (vagy csak "olcsóbb" ha nem nagy a tábla), mint egy Descartes szorzat. Én napi szinten használok analitikus SQL kifejezéseket millió soros táblákon Oracle-ben és szerintem nagyon jól optimalizált a futtató mögötte. Tény, hogy ebbe az Exadata is besegít.
Értem, és köszönöm a választ. Én is szeretem elszeparálni egymástól a lazán kapcsolódó dolgokat. SRP FTW!
Az mondjuk valóban egy fontos kérdés, hogy mi lehetett a kérdező szándéka. Tök érdekes látni, hogy ennek hiányában két egészen eltérő megoldás is született. Az, hogy nem akarja szemmel verni, mindkét esetben teljesül. De hogy ezután mihez kezd velük... arra lehet, hogy egy harmadik megoldás lesz az ideális.
Mondjuk már engem is érdekel a pontosítás. Csak egymást követőek a kérdésesek vagy a teljes tábla?
Ebben az esetben
- ha csak az előzővel kell összehasonlítani, akkor a LEAD vagy LAG megoldás jó lehet. De 3. és 4. sor nem lesz hiba. Hisz növekszik a dátum.
- ha a teljes táblára kell nézni, azaz ha van olyan dátum a megelőző sorokban, ami kisebb, akkor az összes olyan sort adja vissza, akkor a Descartes szorzat a nyerő. A példában a legkisebb a 2020.01.01, így minden előtte levő hibás.
Első esete szerintem azért nem lesz jó, mert ha kijön, hogy a 3. sorban lévő dátum kisebb, mint az előtte levő, azt lehet javíttatod. Majd újra futtathatod, amíg az összes sort rendbe nem teszik.
Ha nincs 2-300000 sor a tábla, lehet kitenném Excel-be a felhasználóknak és tennék rá egy feltételes formázást, =B2<B3, azaz ha kisebb a Dátum mező az előzőnél, akkor színezze ki nekik. A felhasználók többsége imádja a színeket.
Mess with the best / Die like the rest
Sziasztok,
Van egy selectem ami count-ol. Tök jól is működik. Viszont előfordul olyan is, hogy nincs a selectnek eredménye. Meg tudom az csinálni valahogy hogyha nincs eredmény, akkor a visszaadott érték 0 legyen, ne pedig semmi?
Egy excel macroval futtatom a selectet, és elég zavaró a semmi :D
Milyen sql?
NVL() függvény pl. Oracle-ben.
Az egész select-et tedd be az NVL első paraméterbe. (zárójelben)
NVL(
(select count(*) from...)
, 0)
Ez akkor jó, ha lehet olyan eset, hogy ha egy sorral sem tér vissza a lekérdezés.
[ Szerkesztve ]
Nekem így nem akar működni.
de ha a COUNT után nem csillagot, hanem a táblát írom, így elhagyhatom a Group-ot a végéről, és így működik is rendesen Köszönöm szépen a segítséget
szívesen.
úgy tudod azt futtatni, hogy beteszed egy fiktív lekérdezésbe:
select
NVL(
(select count(ID) from TABLANEV)
, 0) as OSZLOPNEV
from dual;
ezt kihagytam az előbb, bocsi.
Köszönöm, holnap kipróbálom.
A nyavajás from dual-t hagyom le mindig a végéről :)
Egyáltalán kell egy plusz lekérdezés az Oracle specifikus from dual szintaxissal?
Nem lenne egyszerűbb egy
select nvl(count(*),0) from tablanev;
[szerk:]Hmm,Oracle 11G2 amúgy is 0-t ad vissza count(*)-ra, ha nincs egy rekord se a táblában, nem NULL-t.
[ Szerkesztve ]
Hello IT! Have you tried turning it off and on again?
Sziasztok!
Évente külön táblában (T20, T19 stb) tárolt KOD, TIPUS, ÉRTÉK adatokat szeretnék lekérni:
KOD, TIPUS, ÉRTÉK_19, ÉRTÉK_20, változás%
formában, hogy az azonos KOD és TIPUS adatok egy sorban legyenek és akkor is megjelenjen, ha csak az egyik táblában szerepel (Oracle).
Köszönöm.
select kod,
tipus,
t19.ertek ertek_19,
t20.ertek ertek_20,
((t20.ertek/t19.ertek)-1)*100 valtozas
from t19
full join t20
on t19.kod = t20.kod
and t19.tipus = t20.tipus;
[ Szerkesztve ]
Hello IT! Have you tried turning it off and on again?
Biztos csak én nem látom a fától az erdőt...
A max dátumhoz tartozó km kellene rendszámonként (mssql)
SELECT MAX(Datum), Rendszám, Km
FROM tankolas
GROUP BY Rendszám, Km
Antonio Coimbra de la Coronilla y Azevedo, bizony!
Először le kéne válogatni rendszámonként az utolsó dátumot, majd azokhoz a rendszám-dátum párosokhoz tartozó km értéket kikeresni a táblából.
Alselect helyett joinnal:
select
t.datum,
t.rendszam,
t.km
from tankolas t
join (select rendszam,
max(datum) max_datum
from tankolas t
group by rendszam) t2
on t.rendszam = t2.rendszam
and t.datum = t2.max_datum;
Vagy rendszámonként besorszámozod dátum szerint csökkenőbe, és minden rendszámhoz az első rekordot veszed:
select datum,
rendszam,
km
from (select datum,
rendszam,
km,
row_number() over (partition by rendszam order by datum desc) rn
)
where rn=1;
Egyébként ha meg feltételezzük, hogy a km állás monoton növekvő (magyarul nem szokták babrálni az órát), akkor egyszerűbben is lehet, hiszen a max(datum) és a max(km) érték ugyanazon a rekordon kéne hogy legyen:
select rendszam,
max(datum) datum,
max(km) km
group by rendszam;
De ilyet ne feltételezzünk, mert a valóság az, hogy ahány adatrögzítő, annyiféleképpen sikerült bevinnie az adatot az évek során.
[ Szerkesztve ]
Hello IT! Have you tried turning it off and on again?
Lehet, hogy az első logikája érthetőbb lenne CTE szintaxissal:
with utolso_tankolas as
(select rendszam,
max(datum) max_datum
from tankolas t
group by rendszam)
select
t.datum,
t.rendszam,
t.km
from tankolas t
join utolso_tankolas t2
on t.rendszam = t2.rendszam
and t.datum = t2.max_datum;
Hello IT! Have you tried turning it off and on again?
Köszönöm, jó is lenne.
De annyival bonyolódik, hogy t19-et szűrni is kellene, összekapcsolva egy másik táblával. From kiegészül és a végén Where-el összekapcsolva a t19 és az uj tábla. Ekkor viszont már ér!vénytelen azonosítót jelez az ON részben.
Ha jól gondolom, +join kell a 3. táblára
[ Szerkesztve ]
A gond a km. Group by esetén a csoportosított halmazon belül fogod megkapni a max dátumot, azaz először a rendszám és km lesz összevonva, majd ezen belül a max dátum. A többit nyunyu leírta...
"Debugging is like being the detective in a crime movie where you're also the murderer."
tulajdonképpen igazad van, mert nvl nélkül is 0-t ír, viszont Pulsar kérdése esetében nem azt írt ezért kellett az NVL.
A plusz lekérdezést én a példánál bonyolultabb függvényekben használtam, ott jelentkezett ilyen hiba a visszaadott NULL érték miatt.
Vagyis annyiból nem jo, hogy t20-ból nem jön le az a Tipus, ami csak ott szerepel és t19-ben nem
akkor nem full join-t használsz. azzal le kell jönnie.
Probléma az, hogy a WHERE után írt feltétel az globális.
Ha oda azt írja, hogy t19.ertek>19, akkor minden olyan rekordot vissza fog adni, ahol ez teljesül.
NULL értékekre definíció szerint <,=,> hasonlítás sem teljesül, emiatt kiszűri azokat, ahol csak a T20 táblában lenne jó érték, de a T19-ben nincs.
LEFT/RIGHT/FULL JOINkor emiatt fokozottan figyelni kell a NULLokra.
Tehát valami ilyesmit tud csinálni, hogy
where (t19.ertek is null OR t19.ertek>19)
and ... többi feltétel.
[ Szerkesztve ]
Hello IT! Have you tried turning it off and on again?
Igen, plusz írta, hogy van egy 3. tábla is, ha azt szimpla join-nal kapcsolja a T19-hez, akkor szintén nem fognak lejönni a csak T20-ban szereplők.
De, full van. Van olyan sorom, hogy az ertek_20 üres, de olyan nem jött le, hogy T19 üres és a másik nem. Pedig van ilyen.
Végül is úgy tudtam megoldani, hogy a From-ba került Select-el a másik tábla adata és a Where-be a feltételek. Így lejött minden.
Elsőre azt gondoltam, hogy az egymást követő rekordokra vonatkozó lekérdezés lefedi az esetek egészét, de ez végül téves feltételezésnek bizonyult a részemről és a Descartes-szorzatot használó megoldás több keresett találatot eredményezett. Úgyhogy bambano, tm5 köszönöm szépen mindkettőtöknek
[ Szerkesztve ]
“Mankind invented the atomic bomb, but no mouse would ever construct a mousetrap.” Albert Einstein
Köszönöm, megpróbálom.
Antonio Coimbra de la Coronilla y Azevedo, bizony!
Sziasztok,
Oracle SQL developert használok és az alábbi feladatot szeretném megoldani.
Adott egy pivot-olt lekérdezés, amivel lejön egy kereszttábla, adatokkal.
Példa:
SELECT * FROM
(
SELECT
[EGYED AZONOSITO],
[CSOPORT KEPZO],
[ERTEK]
FROM
[TABLA]
)
PIVOT
(
SUM([ERTEK])
FOR [CSOPORT KEPZO] IN ([A],[B],[C],[...],[Z])
)
Tehát ERTEK összesített adatait CSOPORT KEPZO szerint egymás mellé pakolja minden EGYED AZONOSITO esetén.
Szeretném mellé tenni egy másik kereszttáblába azokat az indexeket, amik úgy képződnek, hogy az EGYED AZONOSITO szerint minden ERTEK-et összeadok CSOPORT KEPZO-től függetlenül és ezzel a fenti tábla megfelelő sorának minden értékét elosztom.
Példa:
Első pivot:
Béla 0,0,15,0,0,30,0,15
Második pivot:
Béla 0,0,0.25,0,0,0.5, 0,0.25
Hogyan tudom ezt megoldani?
Csak tipp: felső selecthez hozzájoinolod az egyedenkénti szummát egy új oszlopba, majd ezzel az értékkel osztod lent a sum(ertek)-et?
select * from (
with egyed_osszeg as
(select egyed_azonosito,
sum(ertek) osszeg
from tabla
group by egyed_azonosito)
select t.egyed_azonosito,
t.csoport_kepzo,
t.ertek,
o.osszeg
from tabla t
join egyed_osszeg o
on t.egyed_azonosito = o.egyed_azonosito
)
pivot
( sum(ertek)/osszeg
for csoport_kepzo in ('A','B'...)
)
Hello IT! Have you tried turning it off and on again?