Hirdetés
- gban: Ingyen kellene, de tegnapra
- MasterDeeJay: i7 4980HQ asztali gépben (vs i7 4770)
- D1Rect: Nagy "hülyétkapokazapróktól" topik
- sh4d0w: Árnyékos sarok
- sziku69: Szólánc.
- sziku69: Fűzzük össze a szavakat :)
- Luck Dragon: Asszociációs játék. :)
- Magga: PLEX: multimédia az egész lakásban
- juhi11: Karácsony esély, hogy észrevegyük: mások is valakik - még Isten is
- btz: Internet fejlesztés országosan!
Új hozzászólás Aktív témák
-
nyunyu
félisten
Erre nem lenne célszerűbb írni egy before insert (Oracle) vagy instead of triggert (MS SQL) * ami azt csinálja, hogy ha már van fej_id, tetel_id, ar, kedv értékekkel sorod, akkor annak mennyiségét, értékét megnöveli az újonnan beszúrandó mennyiséggel, mennyiség*árral?
Ha meg nincs, akkor beszúrja az új sort?Mondjuk a táblákra aggatott triggerek nem szokták növelni a DB logika átláthatóságát

*: pontos szintaxisuk nekem sincs meg fejben.
-
nyunyu
félisten
Szerkesztési idő lejárt.

Ha az ügyfélnek két azonos időbélyegű előfizetése van, akkor a row_number() -es megoldás véletlenszerűen vagy az egyiket vagy a másik státuszát fogja visszaadni, így csak 1 sor fog hozzá tartozni.
Míg a másik két opció mindkét legfrissebb előfizetés státuszát visszaadja, azokkal egy ügyfélhez 2 sort fogsz kapni.(Ha a row_number()-t rank()-ra cseréled, akkor az is mindkettőt vissza fogja adni.)
-
nyunyu
félisten
Mármint sokkal egyszerűbb, mint ügyfelenként meghatározni az utolsó előfizetési dátumot, és az ahhoz tartozó rekordot visszakeresni az előfizetés táblában, hogy utána joinolhassam az előfizetőhöz:
select u.*, s.status
from users u
left join (
select *
from subscription
where (customer_id, createdate) in (
select customer_id, max(createdate)
from subscription
group by customer_id) s
on s.customer_id = u.customer_id;(Tényleg, Oraclen kívül van más olyan DB is, ami támogatja a sokoszlopos IN / NOT IN műveleteket?
Ha jól rémlik, ez a szintaxis nincs szabványosítva)Valószínűleg ablakozós max() függvénnyel is lehetne írni, és akkor nem kellene a group by köré írt külső query:
select u.*, s.status
from users u
left join (
select *
from subscription
where createdate = max(createdate) over (partition by customer_id)
) s
on s.customer_id = u.customer_id;Talán így a legrövidebb a kód.
-
nyunyu
félisten
select u.*, s.status
from users u
left join (
select x.*,
row_number() over (partition by customer_id order by created desc) rn
from subscription x
) s
on s.customer_id = u.customer_id
and s.rn = 1;Beszámozod a subscription táblát ügyfelenkénti létrehozási dátum szerint csökkenőbe, aztán ebből joinolod az első rekordot az usershez.
(Nem szeretek alquerykben group by-jal bohóckodni, mert úgy sokkal hosszabb+bonyolultabb+olvashatatlanabb lenne a kód.)
-
-
nyunyu
félisten
válasz
bambano
#5924
üzenetére
Az a bajom, hogy túlzottan alulnézetből látom az adatokat, és nem mindig ismer(het)em a keletkezésük, elromlásuk pontos körülményeit a különböző rendszerek közti adatszinkronizációk útvesztőjében, viszont nekem kéne helyrekalapálni a félreálló biteket.
Bár elnézve azt,hogy ~3500 GDPR érett igénylést akartam javítani, de belekerült 10 friss is a szórásba, az csak 0.3% hibaarány, bőven elviselhető kerekítési hiba

-
nyunyu
félisten
Ehh,
and t.torlesi_datum is not nullhelyettand t.torlesi_datum > h.letrehozasi_datumkellett volna, és akkor biztosan nem nyírom ki a rossz ideiglenes számlaszámon létrejött friss igényléseket.
(Véglegeset 1 munkanappal később kaptak volna a számlavezető rendszertől, ami biztosan különböző lett volna a korábbiaktól.)Asszem felírhatom a kéménybe korommal, hogy ez az n+1-edik módszer, ahogy a rendszerünk képes elkefélni az adatokat.
-
nyunyu
félisten
válasz
bambano
#5921
üzenetére
De kéne.
Eredeti DBben nem ugyanúgy hívják a hiteligenylesek meg a másik rendszerből származó táblákban a számlaszámos mezőket, így nem akadt fenn azon az Oracle, hogy elfelejtettem táblaaliast írni a select oszlopai elé, mivel egyértelmű volt, hogy melyik táblából jön.
Csak itt a szemléltetés kedvéért olvashatóbbá egyszerűsítettem a kódot, és nem követtetem a DBnk örökölt hülyeségeit, hogy minden táblában másképp hívják ugyanazokat a mezőket, aszerint, hogy ki mikor/hogyan specifikálta.

Pl. createdate vs create_date még az egyszerűbbik eset...
-
nyunyu
félisten
Adott egy ilyen query
update hiteligenylesek
set torolt = 1
where (foszamla, alszamla) in
(select foszamla, alszamla
from hiteligenylesek h
left join torolt_igenylesek t
on t.foszamla = h.foszamla
and t.alszamla = h.alszamla
left join aktiv_igenylesek a
on a.foszamla = h.foszamla
and a.alszamla = h.alszamla
where h.torolt = 0
and t.torlesi_datum is not null
and a.foszamla is null);
Hiteligenylesek táblában vannak a hitelek adatai, torolt_igenylesek és aktiv_igénylesek táblákba be lett importálva a számlavezető rendszer már törölt és aktív állománya január végéig. (torlesi_datum <= január 31)Ehhez képest az Oracle valahogy teret váltott, és a február 29-én létrejött igényléseket is töröltre állította, pedig az azonosítóik sem a torolt_igenylesek, sem az aktiv_igenylesek táblában nem szerepelnek

(torolt flagjük meg nyilvánvalóan 0, hiszen a query futtatása előtti napokban jöttek létre.)Még mindig nem értem, a nincs találat hogyan felel meg az is not null feltételnek.

-
nyunyu
félisten
Nem lehet, hogy az Excel ODBC drivere kavar be?
Nálam Oracle SQL Developerrel is az a helyzet, hogy ha jobb klikk, save as-szel rákattintok az eredményhalmazra, és excel van kiválasztva, akkor egyszerűen megáll, amint eléri a fájlméret a 3MB-t.
Múltkor 3-4 napig vertem szemmel egy 17 ezer soros excelt, mire rájöttem, hogy igazából 25 ezer sort kellett volna átnéznem

Azóta csak csv-be mentek.
-
nyunyu
félisten
Ha valami(ke)t aggregálni szeretnél, akkor a group by-nál fel kell sorolnod minden olyan mezőt, ami a selectnél fel van sorolva és NEM számított mező.
Aggregálandó mezőket viszont nem szabad beírni a group by-hoz.Persze lehetne ablakozó függvényekkel bonyolítani a történetet, hogy ne kelljen group by, de úgy kétszer olyan hosszú lenne a kód, és nehezebb megérteni, mit csinál

select id, kezdes
from (
select id, kezdes, row_number() over (partition by id order by kezdes asc) rn
from tabla)
where rn = 1; -
nyunyu
félisten
válasz
bambano
#5899
üzenetére
Oracleben gyorsan összedobva:
with munkanap as (
select a.*
from (
select to_date('2023-12-31','yyyy-mm-dd') + rownum as actdate, to_char(to_date('2022-12-31','yyyy-mm-dd') + rownum, 'd') as dateid
from (
select rownum r
from dual
connect by rownum <= 5000)
) a
left join days d
on d.actdate = a.actdate
and d.dateid = 0
where a.dateid in (1,2,3,4,5)
and d.actdate is null)
select actdate
from (
select m.*, row_number() over (order by actdate asc) rn
from munkanap m
where m.actdate > to_date('2024-12-20','yyyy-mm-dd')) x
where rn = 15;Ahogy néztem reggel, Postgre szintaxissal sokkal egyszerűbb lenne a munkanap CTE.
-
-
nyunyu
félisten
Van lekérdezési rekord limit. Elég csak a munkanapokat egyesével bejegyezni a hr oldal alapján, aztán X1 dátumtól kezdve kérni X2 (vagy X2+1) rekordot, és a legutolsóból kivenni a dátumot. És arra még azt se mondhatja senki, hogy kinézetre csúnya.
Ezért tettem a belső selectbe a row_number()-t, hogy számozza be a találatokat, aztán a külső selectbe meg az rn = 15 feltételt.
Felesleges az egész naptárat visszaadni a frontendnek, ha úgyis csak 1 dátumra van szüksége belőle. -
nyunyu
félisten
válasz
bambano
#5892
üzenetére
Ja, ha multikulti környezetben akarod ezt használni, akkor kell még egy oszlop a days táblába, ahova felveszed az országot/tartományt, aztán a függvénybe/querybe azt a feltételt is beleteszed, hogy melyik ország/tartomány munkanapjait számolja.
De akkor lehet szívni az olyan különbségekkel, mint pl. araboknál péntek-szombat a hétvége, tehát arab országoknál a vasárnap lesz az 1, csütörtök az 5 a táblában.
Meg külön-külön összevadászni+felvinni a helyi ünnepeket... -
nyunyu
félisten
Ne bonyolítsuk ennyire túl, hogy korrekciós tábla, meg json parseolás.
Munkanap tábla karbantartása az max 1 óra/év.
Legalábbis annyi idő alatt dobtam össze DBFiddlében, úgy, hogy ágyban a hasamon a laptoppal pötyögök 2 ujjal, és gugliznom kellett a postgre szintaxisát.
Mondjuk arra nem jövök rá, mi a baja a határidő függvényemmel, mert a fordításkori hibaüzenet nem túl beszédes, de biztosan valami triviális szintaxist néztem be, csak Oraclehoz szokott szemmel nem tűnik fel.
-
nyunyu
félisten
válasz
bambano
#5883
üzenetére
x. munkanap:
select actdate
from (
select d.actdate, row_number() over (order by actdate asc) rn
from days d
where d.actdate > to_date('2024-12-20','yyyy-mm-dd')
and d.dateid in (1,2,3,4,5) --munkanap
)
where rn = 15;
-- 2025-01-17 00:00:00(actdate a dátum mező, dateid-ben van tárolva az 1-7 hétfő-vasárnap, 0 ünnep)
-
nyunyu
félisten
válasz
bambano
#5877
üzenetére
Nálunk ez úgy van megoldva, hogy van egy days tábla, amibe kolléga minden decemberben feltölti előre a következő évi dátumokat, meg mellé, hogy hanyadik napja a hétnek.
Ha valami ünnepnap, akkor 1-7 helyett 8 értéke van, ha meg munkanap áthelyezéses szombat, akkor 5 (péntek) lesz az értékeEzt használva az x. napot követő első munkanap lekérdezés úgy alakulna, hogy megnézed, hogy a kérdéses dátum+x. nap után melyik a legkisebb olyan nap, aminek 1-5 közötti az értéke.
Ha meg x. munkanap kell, akkor a kérdéses dátumnál nagyobbak közül sorbarakod az 1-5 közötti értékűeket, aztán ebből veszed az x. legkisebbet.
-
nyunyu
félisten
Jobban végignéztem a query elejét.
Egyszer a select által visszaadott oszloplistában létrehozol egy bank meg egy penztar oszlop aliast
Lejjebb meg hivatkozol egy bank meg egy penztar nevű táblára, amiket elneveztél t2 meg t4-nek.Nem szerencsés egy queryn belül ugyanolyan aliast definiálni, mint amilyen táblát/aliast használsz máshol.
-
nyunyu
félisten
válasz
DeFranco
#5869
üzenetére
Nem fordítva írod?
select * from T1
left join T2 on T1.azon=T2.azon
ami az egyenlet bal oldalán van (T1) abból minden és T2-ből az egyező.Elvileg a kettő ekvivalens, aztán onnantól kódolási stílus kérdése/hitvita, hogy azt a táblát írjuk előre, amelyiket akarjuk joinolni (T2) a korábbiakhoz (T1), vagy amelyikhez joinoljuk (T1) az újat (T2)
Amit benézhetett az az, hogy az SQL-92 szabvány előtti Oracle join szintaxisban a Where mögött explicite jelölni kellett, hogy melyik oldalnál megengedett a null, és ha arra az aliasra voltak extra feltételek, akkor ott is:
FROM kimszamla AS t1, banklista AS t2, bank AS t3
WHERE t1.tipus='0'
AND t1.teljesites <= '2023-01-01'
AND t2.szamla_id (+) = t1.szamla_id
AND t3.bank_id (+) = t2.bank_id
AND t3.datum (+) <= '2023-01-01'(Tradícionálisan itt írták előre a régi táblát aztán az egyelőség után az újat a (+)-szal, az jelölte a left joint, fenti példában right joinnak látszik.)
-
nyunyu
félisten
WHERE t1.tipus='0'
AND t1.teljesites <= '2023-01-01'
AND t3.datum <= '2023-01-01'Wherehez írt feltételek erős szűrési feltételek.
Ha nincs t3-ból találat, akkor a t3.datum <='2023-01-01' ki fogja szűrni az egész t1 sorát, mintha erős join lenne.Próbáld meg áttenni a left joinolt táblákra vonatkozó feltételeket a left join ON-ja után:
LEFT JOIN bank AS t3 ON t3.bank_id=t2.bank_id AND t3.datum <= '2023-01-01'Where mögött csak az eredeti táblára, és hozzá erősen joinoltakra vonatkozó feltételek maradjanak.
-
nyunyu
félisten
create view v_ajandek as
select tetel, sum(netto) sum_netto, sum(brutto) sum_brutto
from dbo.Ajandek
group by tetel;Lényeg az, hogy minden a group by-ban nem megadott oszlopra valamilyen aggregáló függvényt (min, max, count, sum, avg...) kell használni, esetedben mindkét oszlopra külön-külön szummázol.
-
nyunyu
félisten
Van ilyen update szintaxis? *
Szerettek veszélyesen élni.
Én inkább szabvány merge-et írnék:
MERGE INTO Tabla t
USING (SELECT ceg, adoszam, datum,
ROW_NUMBER() OVER (PARTITION BY ceg ORDER BY datum DESC) rnum
FROM Tabla) x
ON (t.ceg = x.ceg
AND t.adoszam = x.adoszam
AND t.datum = x.datum)
WHEN MATCHED THEN
UPDATE SET t.Rel = CASE WHEN x.rnum = 1 THEN 1 ELSE 0 END;(Gondolom a régebbi adószámokat egyúttal rel=0-ra kell állítani.)
* Ja tényleg, SQL Server 2008 környékén próbálták elcsaklizni a Teradata ügyfeleit, aztán emiatt implementálták a Teradata tuningolt update szintaxisát a FROM clause-zal.
-
nyunyu
félisten
Általában igyekszem szabványos SQLül írni, de van amire nincs szabvány, és ahány DB, annyiféle szintaxis létezik rá.
Ilyen a maradékos osztás is.Meg úgysem a pontos szintaxis a lényeg, mert azt viszonylag könnyen át lehet írni egyik DB dialektusról a másikra, hanem a mögöttes logika.
-
nyunyu
félisten
Valami ilyesmire gondolsz?
Hogy itt is megmaradjon:
with nev_lista as
(select nev,
--row_number() over (order by nev asc) id,
mod(row_number() over (order by nev asc)-1,10) oszlop,
trunc((row_number() over (order by nev asc)-1) / 10) sor
from nevek)
select *
from nev_lista
pivot(
max(nev)
for oszlop
in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
)
order by sor;SQL szeret mindent 1-től számozni, ez most nekünk nem praktikus, ezért van a sorszám-1 osztva 10-zel.
Melóhelyen szórakoztattam egyszer magamat azzal, hogy az időzített jobokat vezérlő táblából (id, folyamatnév, melyik_nap, kezdő_idő, vége_idő) rajzoltam heti naptárat negyedórás bontásban, az jóval nagyobb szopás volt

Pláne, hogy éjfélen túlnyúló folyamataink is vannak
-
nyunyu
félisten
Nem lehet állítani az IDEdben, hogy milyen területi beállításokkal értelmezze/jelenítse meg a számokat/dátumokat?
Gondolom az SQL Management Studioban is állítható, nem csak az SQL Developerben.
Meg mire van állítva a szerver? (SQLPlus pl. a szerver beállításait használja)
-
nyunyu
félisten
Jim74 válaszát kiegészítve, hogy a példádat adja ki:
select t1.NAME,
coalesce(t2.Created_date, 'NINCS') Created_date,
coalesce(t3.Description,'NINCS') Description
from tabla_1 t1
left join tabla_2 t2
on t2.ID = t1.ID
left join tabla_3 t3
on t3.ID = t2.ID2
where t1.NAME in ('A','B','C','D','E','F','G')
order by t1.NAME;(Eredetileg nvl()-lel akartam írni, de az Oracle specifikus függvény, ahogy az isnull() SQL Serveres, egyik sem szabvány SQL.
Coalesce() az elvileg szabványos, minden DBben működnie kéne.) -
nyunyu
félisten
select akt.id,
akt.time aktualis_ido,
akt.counter aktualis_allas,
elozo.time elozo_ido,
elozo.counter elozo_allas,
akt.time - elozo.time eltelt_ido,
extract(day from (akt.time - elozo.time)*24*60*60)/60 eltelt_ido_perc,
akt.counter - elozo.counter allas_valtozas,
(akt.counter - elozo.counter)/extract(day from (akt.time - elozo.time)*24*60*60)/60 atlag_fogyasztas
from oraallas akt
left join oraallas elozo
on elozo.id = akt.id - 1
order by id; -
nyunyu
félisten
Sebtében összetákolt Oracle példa:
create table gazora (idobelyeg timestamp, allas number);
insert into gazora (idobelyeg, allas)
values (systimestamp, 70);
insert into gazora (idobelyeg, allas)
values (systimestamp-1, 65);
with oraallas as (
select idobelyeg,
allas,
row_number() over (order by idobelyeg desc) rn
from gazora
)
select akt.idobelyeg aktualis_ido,
akt.allas aktualis_allas,
elozo.idobelyeg elozo_ido,
elozo.allas elozo_allas,
akt.idobelyeg - elozo.idobelyeg eltelt_ido,
extract(day from (akt.idobelyeg - elozo.idobelyeg)*24*60*60)/60 eltelt_ido_perc,
akt.allas - elozo.allas allas_valtozas,
(akt.allas - elozo.allas)/extract(day from (akt.idobelyeg - elozo.idobelyeg)*24*60*60)/60 atlag_fogyasztas
from oraallas akt
join oraallas elozo
on elozo.rn = akt.rn + 1
where akt.rn = 1;CTE-ben megfordítottam a számozás irányát, hogy fixen rn=1 legyen a legutolsó rekord, eggyel nagyobb az eggyel régebbi.
join feltételben lévő on elozo.rn = akt.rn + 1 feltétellel tudsz játszani, hogy hány méréssel korábbi rekordhoz képest akarsz eltérést, átlagot számolni.(interval adattípus miatti típuskonverzióért elnézést, nem lehet értelmesen percre váltani.)
-
nyunyu
félisten
Tetszőleges két időpont közötti: lekérdezed a két időpont közötti rekordokat, és a max(óraállás)-ból kivonod a min(óraállás)-t, max(időbélyeg)-min(időbélyeg) megmondja, mennyi idő alatt, kettőt osztva megvan az átlag.
(Feltételezve, hogy az óraállás monoton nő, és nincs visszatekeréses buhera.)Egy perccel korábbihoz képesti változáshoz meg össze kéne joinolnod az aktuális rekordot az eggyel előzővel, és úgy kivonni az óraállásokat, időbélyegeket.
Itt az időbélyeg - 1 perc mint join feltétel nem biztos, hogy járható út, mert nem biztos, hogy kereken percenként van új rekord, inkább be kéne számozni a rekordokat egy row_number() over (order by timestamp)-kel, aztán úgy joinolni a saját rn -1-gyel. -
nyunyu
félisten
Van egy táblád, amiben van egy menet_id, egy fogadas_id, meg egy nyert mező?
8x összejoinolod önmagával, menet_id = menet_id, következő fogadas_id = előző fogadas_id+1, nyert mindig 1?
select f1.menet_id,
f1.fogadas_id kezdo_fogadas_id
from fogadas f1
join fogadas f2
on f2.menet_id = f1.menet_id
and f2.fogadas_id = f1.fogadas_id + 1
and f2.nyert = 1
join fogadas f3
on f3.menet_id = f1.menet_id
and f3.fogadas_id = f1.fogadas_id + 2
and f3.nyert = 1
join fogadas f4
on f4.menet_id = f1.menet_id
and f4.fogadas_id = f1.fogadas_id + 3
and f4.nyert = 1
join fogadas f5
on f5.menet_id = f1.menet_id
and f5.fogadas_id = f1.fogadas_id + 4
and f5.nyert = 1
...
where f1.nyert = 1; -
nyunyu
félisten
válasz
Postas99
#5707
üzenetére
Próbálom összefoglalni, hogy mit szeretnél:
- A táblához kéne C-nek azt az elemét kapcsolni, ami a B tábla szerint éppen érvényes.Sima ügy, A-hoz hozzájoinolod a B éppen érvényes rekordját *, aztán ahhoz joinolod a C-t.
Valahogy így:
SELECT a.csnev,
a.knev,
a.adoaz,
a.szulido,
c.elemnev As Neme,
b.elemid,
alkalmazas.datumtol,
alkalmazas.datumig,
kapcsolatok.lista AS KapcsolatLista
FROM a
INNER JOIN b
ON a.szemelyid = b.szemelyid
AND b.datumtol <= getdate()
AND nvl(b.datumig, getdate() + 1) > getdate()
INNER JOIN c
ON b.elemid = c.elemid
INNER JOIN alkalmazas
ON a.szemelyid = alkalmazas.szemelyid
INNER JOIN (SELECT szemelyid,
STRING_AGG(adatok, ',') WITHIN GROUP (ORDER BY adatok) AS lista
FROM kapcsolat
GROUP BY szemelyid) kapcsolatok
ON a.szemelyid = kapcsolatok.szemelyid;Persze lehetne a
nvl(b.datumig, getdate() + 1) > getdate()helyettb.datumig IS NULL-ot írni, de így bolondbiztosabb, meg a későbbiekben sem kell módosítani, ha netán valaki '2099-12-31'-et ír be az érvényesség vége mezőbe.*: előbb szokás szerint eggyel túlgondoltam, aztán máris az esetleges adathibák jártak az eszemben .
Szakmai ártalom
-
nyunyu
félisten
válasz
Postas99
#5701
üzenetére
Ebből kb. ennyit sikerült megérteni:
Egy kitétemény van még amennyiben egy FIX érték többször szerepel abbból csak a VALID értéket kell megjeleníteni amit a b.ervenyessegvege mező szabályoz. HA az érték NULL akkor az az adat a valid.De ezt sem teljesen.
Ha az érvényességre akarsz szűrni, akkor kell a b tábla join feltételei közé (vagy a query végi WHERE-be) egy
b.ervenyessegkezdete >= getdate() AND
nvl(b.ervenyessegvege, getdate() +1 ) > getdate()
(vagy hogy hívják MS SQL-ül az oracles sysdate-et)Viszont akkor az összes olyan találatot ki fogod szűrni, amihez már csak lejárt b rekordok vannak.
Vagy ha kettőnek nincs lejárati dátuma, akkor mindkettőt megkapod.Egyébként meg az ilyen adathibák javítására hogy egy b-ből nincs érvényes (vagy több érvényes van), nem az a megoldás, hogy egy feleslegesen túlbonyolított queryvel próbálod kiszűrni őket, hanem kézzel be kéne updatelni az érintett rekordokon az érvényesség eleje, vége dátumokat JÓ értékre, hogy egy időszakra PONTOSAN EGY érvényes rekord legyen.
(Tudom, könnyű ezt mondani, de a rendszerszervezőnknek tavaly nyár óta nincs ideje arra, hogy meghatározza, hogy a többszörös cím, meg telefonszám adataink közül melyik példányt tartsam meg érvényesnek. Közben volt még pár adatmigrációs projekt is, ami extra izgalmakat okozott.
) -
nyunyu
félisten
Szerintem nem akarod tudni, hogyan generáltam dinamikus SQLlel másik dinamikus SQLt, ami generálta helyettem a végleges kódot, ami ~500 táblából vasvillával hányja ki a GDPR érett ügyfelek összes kapcsolódó rekordját.
(Nem volt kedvem kézzel végignyálazni a foreign keyeket, plusz megírni a szükséges joinokat.)
-
nyunyu
félisten
Alapjáraton utálom a dinamikus SQLt, pláne még ha debugolni is kell.
Az meg az extra perverzióm, hogy a dinamikusan összerakott string is olvasható maradjon, azért van benne az a sok CR-LF összefűzés benne. -
nyunyu
félisten
Tarzan erős jeligére:
create table tabla (
ID number,
month number,
country char(2),
ertek number);
insert into tabla (ID, month, country, ertek)
values (1, 1, 'HU', 100);
insert into tabla (ID, month, country, ertek)
values (1, 2, 'HU', 200);
insert into tabla (ID, month, country, ertek)
values (1, 3, 'HU', 300);
insert into tabla (ID, month, country, ertek)
values (1, 1, 'AT', 50);
insert into tabla (ID, month, country, ertek)
values (1, 3, 'AT', 500);
insert into tabla (ID, month, country, ertek)
values (1, 1, 'DE', 100);
insert into tabla (ID, month, country, ertek)
values (1, 2, 'DE', 1000);
commit;
declare
v_orszagkod varchar2(4000);
v_sql varchar2(4000);
begin
select listagg('''' || country || '''', ', ')
within group (order by country)
into v_orszagkod
from (select distinct country from tabla);
--dbms_output.put_line(v_orszagkod);
v_sql := 'create table pivot_table as' || chr(13) || chr(10) ||
'select *' || chr(13) || chr(10) ||
'from tabla' || chr(13) || chr(10) ||
'PIVOT (' || chr(13) || chr(10) ||
' SUM(ertek)' || chr(13) || chr(10) ||
' FOR country' || chr(13) || chr(10) ||
' IN (' || v_orszagkod || ')' || chr(13) || chr(10) ||
')' || chr(13) || chr(10) ||
'where ID = 1' || chr(13) || chr(10) ||
'order by month';
--dbms_output.put_line(v_sql);
execute immediate v_sql;
end;
select *
from pivot_table;
-
nyunyu
félisten
Memory meg core limitek nem úgy értendőek, hogy tökmindegy, mennyi van a gépben, akkor is legfeljebb 4 magot, meg ~2GB RAMot használhat?
(Windows feladatkezelőben meg tudod nézni, hogy éppen mennyit használ.)Ettől persze lényegesen lassabb lesz combosabb lekérdezéseknél, mint a fizetős SQL Serverek, amik a gépben lévő összes procihoz, RAMhoz hozzáférnek. (olcsóbbik Web edition 16 mag, 64GB RAM limites? Átlag asztali PCben nincs annyi.)
-
nyunyu
félisten
Nálunk úgy van megoldva az Oracle alatt megváltozott szerződések továbbítása, hogy rá van téve egy-egy insert meg update trigger a szerződések táblába, ami kiírja egy temp táblába a módosult rekord rowid-ját.
Aztán van egy eljárás, ami a temp táblába kiírt azonosítójú rekordokból felépít egy material viewt a szerződés+kapcsolódó ügyféladatok aktuális tartalmával, majd törli a tempet, ezzel azt érjük el, hogy a matviewban csak az utolsó szinkronizáció óta megváltozott rekordok tartalma lesz meg.
Amikor az SQL Servert használó dokumentumkezelő rendszernek olyanja van, a DBConnectoron keresztül meghívja ezt az eljárást, aztán a matviewban látható aktuális adatokkal megupdateli a saját tábláit.
Nyilván ha két szinkronizáció között többször változik egy rekord (pl. frissül az ügyfél címe, aztán az igazolványszáma), akkor többször fog bekerülni az azonosítója a tempbe, de a belőle épített matviewban már csak egyszer fog szerepelni, a legfrissebb adattartalommal.
-
nyunyu
félisten
Összejoinolod a 3 táblát, majd a wherebe írod a gépnév feltételt.
select g.gepnev, t.*
from gep g
join gep_tartozek gt
on gt.gep_id = g.id
join tartozek t
on t.id = gt.tartozek_id
where upper(g.gepnev) = 'KALAPÁCS';Régi szintaxissal nem írom le, tessenek a szabványt használni.
-
nyunyu
félisten
Alternatív megoldások az, hogy időnként kiírod a változást mondjuk csv-be, átmásolódik a másik gépre, az meg beolvassa? Elég idejétmúlt megoldás, de még mindig működik.
Esetleg MQ, webszerviz.Webszervizért szoktak nálunk a legkevésbé harapni, mondván az illik a legjobban a mikroalkalmazás architektúrába.
Konkrétan még azt se szeretik, ha azonos instanceon lévő másik sémából kéne olvasni ("grant select on tabla to másikséma;"), inkább írattak rá a javásokkal egy új szervizt, amit meg lehet pingelni, aztán az olvassa a választ a másik sémából, vagy írja amit a hívó szeretne.
-
nyunyu
félisten
MS linked servernek hívja ugyanezt a fícsőrt, és ott az ottani szokások szerint központozva kell a querykben megadni, hogy milyen táblát akarsz elérni: [linkeltgépneve.instanceneve].sémanév.dbo.táblanév
-
nyunyu
félisten
Azonos gyártójú adatbázisok között DBLink?
Eltérők között valami 3rd party DB connector megoldás?De ott az IT biztonsági felelősnek is lesz hozzá pár keresetlen szava, tűzfal kivételek, grantok, stb. konfigurálása miatt.
Utána viszont tudsz olyanokat írkálni, hogy
select *
from tabla t
join tabla2@linkneve t2
on t2.id = t.id;Nem én üzemeltetem, így nem tudom, nálunk hogyan vannak konfigurálva az SQL Serverek, meg az Oraclek, de van olyan is, hogy nekem kell Insert ... into tabla@dblink után MS SQL eljárást hívnom, hogy dolgozza fel a külső rendszer, de olyan is bőven akad, hogy SQL Server hívogatja az Oracle eljárásainkat.
-
nyunyu
félisten
SELECT nev,
sum(case when jelenlet NOT IN ('99') AND hianyzas NOT IN ('1') then 1 else 0) AS 'hianyzasoknelkul',
sum(case when jelenlet NOT IN ('99') then 1 else 0) AS 'hianyzasokkal'
FROM tabla
group by nev;Count a nemnull értékek számát adja vissza! (then 1 else null kellene hozzá)
Sum meg az összegét. -
nyunyu
félisten
válasz
Pürrhosz
#5643
üzenetére
1:1-nél mindegy, melyik oldalon van a külső kulcs, működhet az, amit eredetileg elképzeltél.
(Még mindig nem értem az adatmodelledet, ez valami adatpiac akar lenni csillag sémával, ahol A a hub, B, C meg a különböző dimenziói? Akkor eleve A-ba kellett volna tenni a B_index és C_index oszlopokat.)
Akkor:
A-ba B_index felvétele:
ALTER TABLE A ADD COLUMN B_index INTEGER FOREIGN KEY REFERENCES B(B_index);A.B_index mező feltöltése
MERGE INTO A
USING B
ON (A.A_index = B.A_index)
WHEN MATCHED THEN
UPDATE SET A.B_index = B.B_index;Ha nem 1:1 volt eredetileg a kapcsolat, akkor hibaüzenettel el fog szállni!
B-ből a felesleges A_index kidobása:
ALTER TABLE B DROP COLUMN A_index; -
nyunyu
félisten
válasz
Pürrhosz
#5641
üzenetére
Eléggé félremehetett a DB tervezése, ha mindenhol 1 : N reláció lett implementálva. (1 A objektumhoz tartozhat N féle B tulajdonság, ekkor kerül az A_index oszlop a B táblába.)
Igen, ha az A-C viszonyt/kapcsolatot/relációt is N : M-re akarod átalakítani, akkor oda is kell egy új kapcsolótábla, értelemszerűen A_index és C_index oszlopokkal.
-
nyunyu
félisten
válasz
Pürrhosz
#5639
üzenetére
Ha jól értem, akkor neked inkább egy új, AB tábla (a_index, b_index) kéne, az kapcsolná össze az A táblában leírt objektumokat, és a B táblában leírt tulajdonságaikat.
Így tetszőleges N:M kapcsolatot le tudnál írni: egy A-hoz több B tulajdonság is tartozhatna (pl. alma lehet piros, zöld és sárga is), és B tulajdonság tartozhatna több A objektumhoz is. (alma és citrom is sárga).Kapcsoló tábla létrehozása A-ra, B-re mutató külső kulcsokkal:
CREATE TABLE AB (
A_index INTEGER FOREIGN KEY REFERENCES A(A_index),
B_index INTEGER FOREIGN KEY REFERENCES B(B_index)
);
Törölni az AB táblából bármikor tudsz, viszont a külső kulcsok miatt sem az A-ból, sem a B-ből nem fogsz tudni olyan értéket törölni, amire az AB hivatkozik!Feltöltése a meglévő B táblából:
INSERT INTO AB (A_index, B_index)
SELECT A_index, B_index
FROM B;(B táblában ezután már felesleges az A_index mező, el lehet dobni:
ALTER TABLE B DROP COLUMN A_index;
Helyette mindig az AB táblát kell majd joinolni.)Új kombó, pl. zöld alma beszúrása (ha már külön-külön létezik az alma és a zöld is):
INSERT INTO AB (A_index, B_index)
SELECT A.A_index, B.B_index
FROM A
JOIN B
ON 1=1
WHERE A.A_name = 'Alma'
AND B.B_name = 'Zöld';Milyen színű répa van?
SELECT B.B_name
FROM A
JOIN AB
ON AB.A_index = A.A_index
JOIN B
ON B.B_index = AB.B_index
WHERE A.A_name = 'Répa';Melyik gyümölcs sárga?
SELECT A.A_name
FROM B
JOIN AB
ON AB.B_index = B.B_index
JOIN A
ON A.A_index = AB.A_index
WHERE B.B_name = 'Sárga'; -
nyunyu
félisten
Akkor mindenki alapesetben a saját helyi DBjébe írja a koordinátáit, adatait, aztán föléje tesztek egy Java/C# alkalmazást, ami a neten kommunikál a központi DBvel, és ha van net, akkor beszúrja a még fel nem töltött adatokat, majd letölti a többiekét egy másik lokális táblába. *
Ha sikerült a központi szerverről letöltenie a saját koordinátáit, akkor az ahhoz az időbélyeghez tartozó rekordokat meg törli a lokális temp táblából.Arra nyilván figyelni kell, hogy ne legyen ID ütközés: adatok központba feltöltésénél NE a lokális szerver IDját/szekvenciáját használjátok, hanem kérjetek a központi DBből újat, különbön összeütköznének a különböző eszközökről jövő adatok.
Térkép helyi megjelenítésénél meg gondolom a helyi, még fel nem töltött adatokat tartalmazó tábla ÉS a központi szerverről leszinkronizált adatokat tartalmazó táblák unióját kell majd megjelenítened.
Nyilván ha éppen nincs net a hótolón, akkor a többiek által takarított felületből csak annyit tud megjeleníteni, amennyit az előző netkapcsolat idején sikerült letöltenie.
Meg az iroda is csak akkor fog valós idejű adatokat látni, ha éppen van net, kiesett időszakot csak utólag, ha megint net közelbe ér a munkagép.*: Elvileg DB oldalon is fel lehet konfigurálni DB linkeket, interfészeket, és a távoli szerveren lévő táblákat is meg tudja címezni, így akár (percenként) időzített jobokkal is meg lehetne csinálni az adatszinkronizációt, de jártam már úgy Oracle alatt, hogy hálózati hiba miatt leszakadt a DBlink, aztán egyből invalid lett miatta a package a táblanév@DBlink hivatkozás nem létezik címszóval.

Aztán lehetett rugdosni az üzemeltetőket, hogy nyomjon már egy recompile-t az élesen, mert nekem nincs jogom hozzá. -
nyunyu
félisten
válasz
bambano
#5627
üzenetére
az külön necces, hogy egyes gépen hol van net, hol nincs, ahelyett, hogy ilyenkor másik gépen keresztül küldi az adatot, inkább oldjátok meg, hogy legyen net. mibe se kerülne egy építési területre saját wifit telepíteni...
Mondjuk egy Paks2 alapozását ássa 25 munkagép jellegű témánál macerás lehet a saját wifi kiépítése, de mobilnettel megoldható.
-
nyunyu
félisten
Ja, hogy nincs épkézláb noSQL topik?
-
nyunyu
félisten
Értsd már meg, hogy ezt nem engedi a Szent Mikroalkalmazás Architektúra.
Cipész maradjon a kaptafánál, ablakpucolás nem az ő feladata!Hasonlóval szívtam, csak Oracle oldalon: automatizált GDPR törlésekről kellett volna hibajelzéseket küldenem az érintett osztályoknak, hogy vizsgálják ki, milyen adathiba miatt akadt el a folyamat.
Van egy tömeges SMS+email küldő alkalmazásunk, ami feldolgozza a webservicére érkezett kéréseket, így az első ötlet az volt, hogy DBből kéne meghívni a webservice-t.
Oracle persze ebben nem remekel, de azt meg lehet oldani, hogy indít egy shell szkriptet, ami meghívja a servicet.
Mivel minden is agyon van tűzfalazva, így kéne nyitni egy lyukat a DB szerver és az alkalmazásszerver között.
Természetesen ezt a felettesek azonnal letiltották, erről szó sem lehet éles banki környezetben.Második ötlet az volt, ha már az üzenetküldő alkalmazás fizikailag ugyanazon a DBn lóg, mint amin az adatokat törlöm, és a webservice oda pakolja, hogy mikor kinek, mit kell küldeni, akkor használjam direktbe.
Kb. 2 óra volt kisakkoznom, melyik táblájába mit kell írni, hogy menjen az email küldés tőlem.
Jelentem készre a fejlesztést, erre a code reviewn kivágta a biztosítékot az, hogy grant insert on emailszerver.emailtorzs to gdprtorles.
Egyből le lettem ugatva, hogy ezt mégis hogy gondolom hogy csak úgy másik sémába akarok írni, meg hápogtak sokat a Szent Mikroalkalmazás Architektúráról, miszerint az alkalmazások, szerverek nem véletlenül vannak fizikailag és logikailag is elszeparálva, nem kommunikálhatnak csak úgy random össze-vissza egymással.Végül az architektek, rendszerszervezők, üzemeltetők kiokumulálták megoldásnak azt, hogy a saját sémámban csináljam meg az emailtörzs, címzett táblákat, ezt pollozni fogja a DB sémámon lógó Java alkalmazás (amit a többi alkalmazás kérdezget, hogy mik a már törölt azonosítók), aztán az hívja meg az emailküldő servicet, ha kimenő hibaüzenet emailt lát nálam.
Bő 3/4 évvel később élesbe is állt ez a nice to have feature, mert akkor ért rá a javás kolléga ezzel a minor requesttel foglalkozni.
De legalább nem sérült a Szent Mikroalkalmazás Architektúra.

-
nyunyu
félisten
Elég a kettő:
select t1.id, t1.szin, t2.id, t2.szin
from tabla1 t1
left join tabla2 t2
on t2.id = t1.id
and t2.szin = t1.szin
union
select t1.id, t1.szin, t2.id, t2.szin
from tabla1 t1
right join tabla2 t2
on t2.id = t1.id
and t2.szin = t1.szin;Sima union kiszűri az ismétlődéseket az eredménylistából. (union all megtartaná a közös találatok mindkét példányát.)
-
nyunyu
félisten
Erre való a full (outer) join:
select t1.id, t1.szin, t2.id, t2.szin
from tabla1 t1
full join tabla2 t2
on t2.id = t1.id
and t2.szin = t1.szin; -
nyunyu
félisten
Jut eszembe, oszlop egyenlőség vizsgálatokat lehetett volna egyből a where után pakolni:
select t.*
from tabla t
where t.b = t.a
or t.c = t.a
or t.d = t.a
or t.c = t.b
or t.d = t.b
or t.d = t.c;Talán ez lett volna a legegyszerűbb megoldás.
-
nyunyu
félisten
válasz
hellsing71
#5581
üzenetére
Önmagával left joinolod a rekordokat hatszor (4*3/2 oszlopkombináció van, lásd kombinatorika), aztán ha van találat, akkor azok duplikáltak.
select distinct t.*
from tabla t
left join tabla t1
on t1.id = t.id
and t1.b = t.a
left join tabla t2
on t2.id = t.id
and t2.c = t.a
left join tabla t3
on t3.id = t.id
and t3.d = t.a
left join tabla t4
on t4.id = t.id
and t4.c = t.b
left join tabla t5
on t5.id = t.id
and t5.d = t.b
left join tabla t6
on t6.id = t.id
and t6.d = t.c
where t1.id is not null
or t2.id is not null
or t3.id is not null
or t4.id is not null
or t5.id is not null
or t6.id is not null;Persze ehhez az is kell, hogy minden rekordnak legyen egyedi azonosítója (példámban id mező), hogy ne két random rekord oszlopait hasonlítsd össze.
-
nyunyu
félisten
válasz
Petya25
#5569
üzenetére
Jó helyre raktad a zárójeleket?
Meg ahogy rákerestem T-SQL specifikus példákra, feltűnt, hogy mind a PIVOT előtti alquerynek, mind az azutáninak szoktak aliast adni.
Nem tudom, ez mennyire kötelező ott. (Oracle alatt opcionálisak)SELECT * FROM
(
SELECT datum, hely, ertek
FROM tabla
) x
PIVOT
(
SUM(ertek)
FOR datum IN (SELECT DISTINCT datum FROM tabla WHERE datum >= TRUNC(SYSDATE) - 7 ORDER by datum)
) p
ORDER BY hely; -
nyunyu
félisten
válasz
Petya25
#5567
üzenetére
SELECT * FROM
(
SELECT datum, hely, ertek
FROM tabla
)
PIVOT
(
SUM(ertek)
FOR datum IN ('2022-08-15', '2022-08-16', '2022-08-17')
)
ORDER BY hely;Kb. 5 percbe tellett testreszabni az első szembejövő PIVOT példát. (PIVOT szintaxis jóideje szabványos, mindegy melyik DB tutorialját nézed)
Bár lehet, hogy a dátumok kézzel felsorolása helyett elegánsabb lenne alselectet írni:
FOR datum IN (SELECT DISTINCT datum FROM tabla ORDER by datum) -
nyunyu
félisten
Ahogy nézegetem, nem Oracle környezetekben eléggé kihívás a regexp_substr-nek megfelelő funkcionalitás, általában nincs olyan függvény, ami csak a mintának megfelelő részstringet adja vissza.
Pl. MS SQL Servereken lehet bohóckodni a
substr(information, patindex('%[0-9]{13}%', information), 13)-mal.Meg a számjegy osztályra hivatkozást szögletes zárójelbe kell csomagolni: [[:digit:]], ehelyett egyszerűbb/rövidebb a 0-9 karaktereket matchelni, ahogy írtátok a [0-9]-cel.
-
nyunyu
félisten
Szerintem a regexp_like és regexp_substr függvényeket keresi, de utána kéne nézni az adott DB motornál mi a pontos szintaxisuk.
Valami ilyesmire gondoltam:
UPDATE cikk
SET ean = regexp_substr(information, '[:digit:]{13}')
WHERE regexp_like(information, '[:digit:]{13}'); -
nyunyu
félisten
Ja, CTAS nem csak tábla másolásra jó.
Pl. van egy giga lekérdezésed, ami sok táblából lapátol össze adatot, akkor a konkrét végeredményt is el tudod úgy menteni, hogy a SELECT elé írod, hogy
CREATE TABLE <táblanév> ASItt persze figyelni kell arra, hogy az eredeti lekérdezésben minden mezőnév egyedi legyen.
Meg arra is figyelni kell, hogy az eredményhalmazban szereplő leghosszabb string alapján határozza meg a számított VARCHAR() mezők hosszát, így ha a létrehozott táblába akarsz később insertálni, akkor nem biztos, hogy bele fog férni ugyanannak a lekérdezésnek az eredménye, ha mondjuk egy oszlopba két stringet fűzöl össze, aztán később hosszabb stringek lesznek a forrás táblákban... -
nyunyu
félisten
CTAS az emlékeim szerint szabványos szintaxis, mennie kéne nem Oracle DBken is.
Ha a SELECT után nem * áll, akkor csak a hivatkozott oszlopok fognak bekerülni az új táblába az eredeti adattípussal.
* esetén minden oszlop másolódik.Viszont arra figyelni kell, hogy a másolat táblán csak a mezők típusai fognak másolódni.
Constraintek (primary key, foreign key..), indexek NEM, azokat neked kell kézzel létrehozni, figyelve arra, hogy ezek nevei nem egyezhetnek az eredeti táblán használt constraintek, indexek neveivel!CTAS végére írt WHERE mögé írt feltétellel tudod megadni, hogy melyik sorokat másolja át az eredeti táblából.
Ha nincs WHERE, akkor mindent másol, de ha pl. WHERE 1=2;-t írsz, akkor csak a táblaszerkezet fog létrejönni, adatok nélkül. -
nyunyu
félisten
Rendeléseket kérdezted:
Kellene egy lista amibe azon a rendelések vannak amin akad még tennivaló.Amit írtam queryt, az visszaadja mindegyik rendelést, amihez tartozik legalább egy kuldes_id=0 vagy szamla_id =0 tétel.
Ha a konkrét, még nem kész megrendelés tételeik is kellenek, akkor
select t1.rendeles_id, t2.tetel_id
... -
nyunyu
félisten
Akkor az IS NULL-okat cseréld = 0-ra

SELECT DISTINCT T1.rendeles_id
FROM rendeles AS T1
JOIN tetel AS T2
ON T1.rendeles_id=T2.rendeles_id
AND (T2.kuldes_id = 0
OR T2.szamla_id = 0)
WHERE T1.rendeles_id NOT IN (SELECT rendeles_tmp FROM user);Elég háklis szoktam lenni a rendszerszervezőkre, ha olyan mezőkre is specelnek NOT NULL constraint-t, ahol semmi keresnivalója.
Pláne, hogy a kuldes_id-nek, szamla_id-nek logikusan foreign keynek kellene lennie, ami a kuldes, szamla táblák id mezőjére mutat.
Ott meg szigorúan NULL a gyerek tábla mezője, ha éppen nem mutat a szülő egyik rekordjára se! -
nyunyu
félisten
Sokadik olvasatra sikerült megfejtenem, mit is akart jelenteni ez a sor:
AND rendeles_id NOT IN (SELECT IFNULL(rendeles_tmp,0) FROM user)Ha jól értem, amíg a felhasználó nyitott egy tranzakciót, akkor az user tábla rendeles_tmp oszlopba íródik be a félkész rendelés ID-je, és ott is marad, amíg be nem fejezi a vásárlást.
(Remélem egy másik "trigger" takarítja a szemetet utána!
Bár én azt nem triggerre bíznám, hanem explicite kiadnám a delete-et a program kódban.
Ha ilyenekre triggereket használtok, ott valami nagyon félrement az alkalmazás tervezésekor/implementálásakor.)Ekkor viszont a querym végére ezt egy WHERE-be kéne írni:
SELECT DISTINCT T1.rendeles_id
FROM rendeles AS T1
JOIN tetel AS T2
ON T1.rendeles_id=T2.rendeles_id
AND (T2.kuldes_id IS NULL
OR T2.szamla_id IS NULL)
WHERE T1.rendeles_id NOT IN (SELECT rendeles_tmp FROM user);IFNULL(rendeles_tmp,0): ezt meg eleve nem értem, miért kell a null értékeket nullára konvertálni?
Ki nem töltött érték/null az nem része a halmaznak (IN), de az ellenkezőjének sem (NOT IN).(Java programozóink szoktak vért izzadni, mert a DBben a null is értelmes érték.
Azt jelenti, hogy nincs adat.
) -
nyunyu
félisten
Juj.
Először sorbarendezted+csoportosítottad a tételeket rendeles_id szerint, azután az ablakozós függvény a csoportokra külön-külön képezett egy eredményt, aztán az eredményhalmazt még egyszer átfésülted a having után írt feltételekkel?
Nem lenne egyszerűbb egy sima joinnal eleve azokra a tételekre szűrni, ahol a kuldes_id vagy szamla_id null?
SELECT DISTINCT T1.rendeles_id
FROM rendeles AS T1
JOIN tetel AS T2
ON T1.rendeles_id=T2.rendeles_id
AND (T2.kuldes_id IS NULL
OR T2.szamla_id IS NULL);Distinctet csak azért tettem bele, hogy a több hiányos tétellel rendelkező rendelések csak egyszer szerepeljenek a listában, anélkül annyiszor kapnád vissza az azonosítóját, ahány tétele rossz.
Így csak egyszer fog végigmenni a táblákon *, majd az eredmény sorbarendezése után kihagyja a duplikációkat.
* vagy azon se, ha a tetel tablan van egy összetett index a rendeles_id, szamla_id, kuldes_id trióra.
-
nyunyu
félisten
válasz
Panhard
#5540
üzenetére
Nem teljesen értem, hogy mit is szeretnél.
MD5-tel kódolva van letárolva az időbélyeg, és azokra a bejegyzésekre akarsz szűrni amik X és Y dátumok közöttiek?
Az nem lesz egyszerű, mert a hash függvények irreverzibilisek, nem állítható belőlük vissza az eredeti érték, esetedben dátum.
Emiatt a <, >, between operátorokat nem tudod használni két hash érték direkt összehasonlítására.Itt csak azt tudod tenni, hogy kigenerálod X és Y közötti összes dátum MD5 értékét, és azt vizsgálod, hogy az eredeti érték benne van-e ebben a halmazban.
-
nyunyu
félisten
válasz
metaldog
#5534
üzenetére
Nem túl valószínű, hogy ennyire régit be lehetne importálni.
Itt azt írják, hogy a 2012 támogatása is lejár idén júliusban, jelen pillanatban az a legrégebbi verzió, amit lehet 2019-re upgradelni.
Valószínűbb az, hogy a 2008-as DBdet fel kell upgradelned valami kevesebb, mint 10 évvel frissebbre (2016? 2017?), és csak onnan kiexportálva tudnád betenni egy aktuális verzió alá.
-
nyunyu
félisten
IN operátor+alquery:
select *
from adattabla at
where at.azonosito in (select azonosito from temp);De akár JOINnal is szűrhetsz:
select at.*
from adattabla at
join temp t
on t.azonosito = at.azonosito;Régebben a JOINt javasolták a kétféle megoldás közül, mert az gyorsabb volt, manapság már nincs futási idő különbség, mert a (NOT) INt is (ANTI) JOINra fordítja a DB optimalizálója.
-
nyunyu
félisten
Szabvány szerint az IN-nek el kell fogadnia egy alquery eredményét is, amennyiben pontosan egy oszlop széles az eredménye, szóval nem értem miért akarod vesszővel felsoroltatni az UNION eredményét, ahelyett, hogy szimplán beírnád az IN utáni zárójelek közé az egész UNIONos queryt.
Ez egy teljesen valid query:
select *
from tabla
where id in (select id from tabla2 where ertek = 1
union
select id from tabla3 where ertek = 2
union
select id from tabla4 where ertek = 3);Végeredménye 0-3 sor lesz, attól függően hány ID van meg a tablaban.
(Oracle megenged több oszlop széles IN-t is, itt arra kell figyelni, hogy ugyanannyi oszlop legyen az IN két oldalán felsorolva:
where (a,b) in (select c,d from tabla);)Amit te szeretnél, az maximum dinamikus SQLlel oldható meg, amikor futási időben rakod össze stringként a queryt, aztán azt futtatod az erre szolgáló paranccsal (EXEC?), de annak meg jellemzően van valamennyi futási idő overheadje (Oraclenál ~1.5 másodperc?), szóval nem éri a nehezen összerakható, nehezen debugolható kóddal szívni, mert nem lesz gyorsabb.
-
nyunyu
félisten
Hja, ha SQL Servert használsz akkor próbálkozhatsz az archaikus Teradata upsert szintaxissal is, hátha megeszi:
(Elvileg 2008R2-vel próbálták átcsábítani a Teradata DWH júzereit, aztán a legacy kód migráció megkönnyítésére implementálták a Teradata szintaxisát is.)update cc
set cc.cust_partnerkod = cc.cust_partnerkod + x.rn
from cikktorzs_customer cc,
(select id, row_number() over (order by id) rn
from cikktorzs_customer
where cust_partnerkod = 200000) x
where cc.id = x.id;(Hmm, MS csak a SET és a WHERE között engedi a FROM utáni tábla felsorolást? Teradatában a SET elé is lehetett írni, sőt legtöbbször úgy írták.)
De a feljebb írt mergenek biztosan működnie kéne, az a több táblát összefésülő műveletek szabványos írásmódja.
FROM clause nagyon nem szabványos az update szintaxisokban, nem sok DB ismeri, kezeli.
(Oracle alatt meg se próbáld!) -
nyunyu
félisten
""Sok fejfájástól megment, ha több tábla joinja alapján kell updatelni egy táblát..." - de ez egy tábla ..."
Meg kell határoznod, hogy
- melyik sorazonosítóhoz
- milyen értéket szeretnél rendelni.
Ezekből létrejön sok (id, érték) páros, ami kvázi egy újabb tábla/nézet/alselect, ezt kell összefésülnöd az eredeti tábláddal, az meg join művelet. -
nyunyu
félisten
azért, mert egy rekordhoz egyszer kell lefusson, de az első update után változik az adatnézet, ha akkor újra kiértékelődik a belső select, akkor már az eggyel növelt értékű rekordot kellene (mármint a logikám szerint) megtalálnia.
Írtál egy alselectet, aminek összesen 1 rekord az eredménye, és értelmes join feltétel híján sikerült Deschartes szoroznod a tábláddal, vagyis minden sorhoz ugyanazt az 1 értéket rendelte hozzá.
Ha az alselectednek nem 1 sor lett volna az eredménye, akkor DB errort kaptál volna, mert egy mezőnek nem lehet egyszerre több értéket adni.
-
nyunyu
félisten
Javaslom a szabványos merge szintaxis tanulmányozását.
Sok fejfájástól megment, ha több tábla joinja alapján kell updatelni egy táblát...
Egyébként már az updateedet sem értem, miért kéne többször lefutnia az alselectnek, ha egyre limitáltad a visszaadható eredmény számát?
Meg a join feltétel is kompletten hiányzik, ami alapján leválogatnád, hogy melyik rossz sorhoz milyen jó partnerkód tartozna.Ez most pont azt csinálja, hogy leválogatja a legnagyobb partnerkódot, és annyi+1-et ráupdatel minden 200000-es sorra.

Ezzel maximum annyit tudsz csinálni, hogy beteszed egy kurzorba az összes 200000-es sort, aztán egyesével végigiterálva rajtuk mindig eggyel nagyobb értékkel updateled őket.
Vagy valami nagyon elborult merget írsz, ami besorszámozza a sorokat, aztán az alapján updatel:
merge into cikktorzs_customer u
using (select cc.id, cc.cust_partnerkod, row_number() over (order by cc.id) rn
from cikktorzs_customer cc
where cc.cust_partnerkod = 200000) x
on (u.id = x.id)
when matched
then update set u.cust_partnerkod = x.cust_partnerkod + x.rn; -
-
nyunyu
félisten
2 hete jött szembe ennek a durvább verziója: összes ügyfél összes szerződését kellett kötés dátuma szerint csökkenőben beszámoznom, hogy kiderüljön mit kell és mit nem szabad darálni az irattárból, hogy 4 év késéssel megfeleljünk a GDPRnak.
(Még élő ügyfél legfrissebb szerződésén vannak az aktuális adatai, régebbi szerződései darálhatóak csak.)Probléma csak annyi volt, hogy a személy-kapcsoló-szerződés táblák mindegyikének van egy GDPR törlés logja is, így 6 tábla összes létező kombinációját kellett végigsakkoznom.
(hülye jogszabályok miatt ezek eltérő időben törlendőek!)Aztán jól megfeküdt a szerver a sokmilliós táblák keresztül-kasul joinjaitól, így bonthattam 3 felé a feladatot, élő személyek élő szerződései, élő személyek törölt szerződései, törölt személyek törölt szerződései.
Majd a 3 darabban előállított adathalmazra uszítottam rá a row_number() over (partition by person_id order by create_date desc)-et. -
nyunyu
félisten
Felaggregálod a T2-T3 és T4-T5 párosok maximumát szamla_id-kra, aztán azok közül veszed a nagyobbat?
SELECT T1.szamla_id,
T1.vevo_id,
T1.esedekes,
T1.brutto,
case when A.datum is null then B.datum
when B.datum is null then A.datum
when A.datum > B.datum then A.datum
else B.datum
end fizetve
FROM T1
LEFT JOIN (SELECT T3.szamla_id, MAX(T2.datum) datum
FROM T3
JOIN T2
ON T2.id = T3.fej_id
GROUP BY T3.szamla_id) A
ON A.szamla_id = T1.szamla_id
LEFT JOIN (SELECT T5.szamla_id, MAX(T4.datum) datum
FROM T5
JOIN T4
ON T4.id = T5.fej_id
GROUP BY t5.szamla_id) B
ON B.szamla_id = T1.szamla_id
WHERE T1.vevo_id = 'vevőazonosító'; -
nyunyu
félisten
válasz
Prog-Szerv
#5446
üzenetére
Klasszikusan így számolod össze az órákat az összes projektre:
select p.id, p.name, sum(pt.hour) sum_hour
from project p
join project_task pt
on pt.p_id = p.id
group by p.id, p.name;(task tábla tartalma nem ad többlet infót a feladathoz, így azt nem joinoltam feleslegesen a többihez.)
A még nem befejezett projektek kivágására az nem jó, ha beteszel egy where pt.hour>0 feltételt, mert attól még a befejezett részfeladatokat össze fogja adni.
Helyette a komplett project id-t kell kiszűrni, amihez van olyan bejegyzés, ahol a hour = 0:
select p.id, p.name, sum(pt.hour) sum_hour
from project p
join project_task pt
on pt.p_id = p.id
where p.id not in (select p_id from project_task where hour = 0)
group by p.id, p.name;Hány project van, ami teljesen befejeződött?
select count(distinct p.id)
from project p
join project_task pt
on pt.p_id = p.id
where p.id not in (select p_id from project_task where hour = 0);Ide nem kell a fenti group by, mivel most az összes rekordot akarod összeszámolni, és nem projektenként külön-külön.
-
nyunyu
félisten
válasz
DeFranco
#5422
üzenetére
Sima ügy, anonim blokk elé írsz egy declaret:declare
v_valt1 number := 33;
v_valt2 number := 55;
begin
SELECT
table1.col1,
table1.col2 * v_valt1,
table1.col3 * v_valt2
FROM
table1;
end;Mégsem ilyen egyszerű, mert anonim blokkban nem lehet sima select (ahogy eljárás törzsben sem), várja az into táblanevet, hogy milyen táblába irányítsa a kimenetet.
Max úgy működhetne, hogy CTASt írsz a törzsbe:
declare
v_valt1 number := 33;
v_valt2 number := 55;
begin
CREATE TABLE new_table AS
SELECT
table1.col1,
table1.col2 * v_valt1,
table1.col3 * v_valt2
FROM
table1;
end;aztán miután lefutott, akkor le tudod kérdezni egy select * from new_table;-val az eredményt.
-
nyunyu
félisten
válasz
Apollo17hu
#5407
üzenetére
Valami ilyesmire gondolsz?
select a.*, b.*, c.*
from a
full join b
on b.a_id = a.id
full join c
on c.id = b.c_id
where (a.id is not null and b.a_id is null) --A-hoz nincs B kapcsolat
or (c.id is not nll and b.c_is is null) --C-hez nincs B
or (b.a_id is not null and a.id is null and c.id is null); --B-hez nincs A, CMondjuk a B-hez nincs A, C rekordért egy rendes fejlesztőt seggbe kéne rúgni, hiszen pont ezért találták fel a foreign keyeket, hogy ne lehessen ilyet csinálni.
Új hozzászólás Aktív témák
- Drága bluetooth tagek olcsóbb alternatívái (MiLi MiTag, LiTag, OTAG, stb.)
- AMD Ryzen 9 / 7 / 5 9***(X) "Zen 5" (AM5)
- HiFi műszaki szemmel - sztereó hangrendszerek
- Steam Deck
- Mikrotik routerek
- Okos Otthon / Smart Home
- Fizetős szoftverek ingyen vagy kedvezményesen
- Yettel topik
- Filmvilág
- Diablo IV
- További aktív témák...
- Dell Latitude 5400 14" FHD IPS, i5 8365U, 8-16GB RAM, SSD, jó akku, számla, 6 hó gar
- REFURBISHED - DELL Thunderbolt Dock WD19TBS (210-AZBV)
- iPhone 16 128 GB Plus White - Bontatlan !! www.stylebolt.hu - Apple eszközök és tartozékok !!
- Samsung Galaxy S23 Ultra 256GB, Kártyafüggetlen, 1 Év Garanciával
- LG 27GR83Q-B - 27" IPS / QHD 2K / 240Hz & 1ms / NVIDIA G-Sync / FreeSync / DisplayHDR 400
Állásajánlatok
Cég: Laptopszaki Kft.
Város: Budapest
Cég: BroadBit Hungary Kft.
Város: Budakeszi






