Opet, Zidar, svaka cast na fori sa rednim brojevima, majstor si!
Posto cu te jos ponesto pitat u vezi ove iste stvari, ako te ne bude mrzjelo da odgovaras, evo test podataka iz moje baze:
Code:
ID Obveznik Konto Datum_knjizenja Datum_dospijeca Potrazuje Duguje Storno
--------------------------------------------------------------------------------------------------------------
1 1 1 11/29/2008 3:07:06 PM 1/1/2008 12:00:00 AM 56 0 False
2 1 2 11/29/2008 3:07:06 PM 2/1/2008 12:00:00 AM 56 0 False
3 1 1 11/29/2008 3:07:06 PM 3/1/2008 12:00:00 AM 38 0 False
4 1 2 11/29/2008 3:07:06 PM 3/31/2008 12:00:00 AM 0 250 False
5 1 1 11/29/2008 3:07:06 PM 1/1/2008 12:00:00 AM 10 0 False
6 1 2 11/29/2008 3:07:06 PM 4/1/2008 12:00:00 AM 38 0 False
7 1 1 11/29/2008 3:07:06 PM 4/11/2008 12:00:00 AM 0 50 False
8 1 2 11/29/2008 3:07:06 PM 1/1/2008 12:00:00 AM 14 0 False
9 1 1 11/29/2008 3:07:06 PM 3/1/2008 12:00:00 AM 22 0 False
10 1 2 11/29/2008 3:07:06 PM 4/1/2008 12:00:00 AM 15 0 False
Obveznik i konto su strani kljucevi drugih tabela. Obveznika ce biti oko 500, a konta ce biti 5 plus jos jedan konto na koji se uplacuju kamate.
Evo kako sam ja rijesio problem:
Code:
WITH Buff(ID, Obveznik, Konto, Datum_knjizenja, Datum_dospijeca, Potrazuje, Duguje, Saldo) AS
(SELECT * FROM Data UNION (SELECT (SELECT MAX(ID)+1 FROM Data), 1, 1, Getdate(), Getdate(), 0, 0, 0))
SELECT DISTINCT Buff.Datum_dospijeca,
(SELECT(SUM(t.Duguje - t.Potrazuje)) AS Saldo FROM Buff t WHERE t.Datum_dospijeca <= Buff.Datum_dospijeca) AS Saldo,
Coalesce(
DateDiff(
day,
Buff.Datum_dospijeca,
(SELECT MIN(t3.Datum_dospijeca) FROM Buff t3 WHERE t3.Datum_dospijeca > Buff.Datum_dospijeca)
)
,0) AS ProtekloDana,
(SELECT(SUM(t.Duguje - t.Potrazuje)) AS Saldo FROM Buff t WHERE t.Datum_dospijeca <= Buff.Datum_dospijeca) * 0.0003 *
Coalesce(
DateDiff(
day,
Buff.Datum_dospijeca,
(SELECT MIN(t3.Datum_dospijeca) FROM Buff t3 WHERE t3.Datum_dospijeca > Buff.Datum_dospijeca)
)
,0) AS Kamata
FROM Buff
ORDER BY Datum_dospijeca
Rezultat queryja:
Code:
Datum_dospijeca Saldo ProtekloDana Kamata
--------------------------------------------------------------
2008-01-01 00:00:00.000 -80 31 -0.744
2008-02-01 00:00:00.000 -136 29 -1.1832
2008-03-01 00:00:00.000 -196 30 -1.764
2008-03-31 00:00:00.000 54 1 0.0162
2008-04-01 00:00:00.000 1 10 0.003
2008-04-11 00:00:00.000 51 234 3.5802
2008-12-01 18:08:37.187 51 0 0
Ja sam isao drugim pravcem, mjesto da mnozim Saldo jednog reda sa ProtekloDana narednog reda, ProtekloDana racunam kao razliku trenutnog i sledeceg, a ne kao razliku trenutnog i proslog kao prije, tako da vec imam Saldo i ProtekloDana u istom redu. I to je radi super.
Medjutim, odamah ima nesto sto ne razumijem. Naime, ne mogu da referencirama kolone na osnovu alijasa, nego mi izbacuje gresku tipa ne moze da nadje kolonu Saldo i ProtekloDana, pa mjesto prostog Saldo * ProtekloDana moram ponovo da pisem izraze. Valjda je SQL server dovoljno pametan, pa nece istu stvar dva puta racunat, ali mi nije jasno zasto alijasi ne rade. Koristim SQL Server Express 2005.
Onda, vec razmisljam dalje, htio bih da napravim upit koji ce mi dati gotove iznose kamata za svakog obveznika i konto.
Zbog toga sam proba da rijesim isti problem bez WITH:
Code:
SELECT DISTINCT Data.Datum_dospijeca,
(SELECT(SUM(t.Duguje - t.Potrazuje)) AS Saldo FROM Data t WHERE t.Datum_dospijeca <= Data.Datum_dospijeca) AS Saldo,
Coalesce(
DateDiff(
day,
Data.Datum_dospijeca,
(SELECT MIN(t1.Datum_dospijeca) FROM Data t1 WHERE t1.Datum_dospijeca > Data.Datum_dospijeca)
)
,0) AS ProtekloDana,
(SELECT(SUM(t.Duguje - t.Potrazuje)) AS Saldo FROM Data t WHERE t.Datum_dospijeca <= Data.Datum_dospijeca) * 0.0003 *
Coalesce
(DateDiff(
day,
Data.Datum_dospijeca,
(SELECT MIN(t1.Datum_dospijeca) FROM Data t1 WHERE t1.Datum_dospijeca > Data.Datum_dospijeca)
)
,0) AS Kamata
FROM
(
SELECT * FROM Data
UNION
(
SELECT (SELECT MAX(ID)+1 FROM Data), 1, 1, GetDate(), GetDate(), 0, 0, 0
)
) AS Data
ORDER BY Datum_dospijeca
Ali pogledaj rezultat:
Code:
Datum_dospijeca Saldo ProtekloDana Kamata
--------------------------------------------------------------
2008-01-01 00:00:00.000 -80 31 -0.744
2008-02-01 00:00:00.000 -136 29 -1.1832
2008-03-01 00:00:00.000 -196 30 -1.764
2008-03-31 00:00:00.000 54 1 0.0162
2008-04-01 00:00:00.000 1 10 0.003
2008-04-11 00:00:00.000 51 0 0
2008-12-01 18:19:09.857 51 0 0
Tu je druga stvar koju ne razumijem. Ako stavim da je alijas FROM odjeljka BILO STA DRUGO osim rijeci DATA, prilikom pozivanja procedure prijavice mi gresku 'ne mogu da nadjem objekat, recimo, 'Test'. Tek kad stavim da je alijas DATA procedura onda prodje, ali se zadnji - UNION - zapis ne obradjuje. Uzmimo predzadnji zapis, datum 2008-04-11. Imamo vrijednost nula u koloni ProtekloDana, sto znaci da zadnje uporedjivanje t.Datum_dospijeca > Data.Datum_dospijeca daje false, pa SELECT MIN daje Null. Dakle, SELECT MIN ne vidi zadnji zapis. Kolona Saldo sadrzi ispravnih 51, jer ona zavisi samo od proslih zapisa i trenutnog zapisa (<=) dok kolona ProtekloDana zavisi od trenutnog i sledeceg (>). Ali ipak, eto ga zadnji zapis u rezultatu.
Problem je vjerovatno sto sam alijas nazvao Data. Ko zna koje Data SQL Server odje koristi, tabelu Data ili alijas Data???
Sto se tice zbirnog upita za sve obveznike, mora se opet preko ovih ugnjezdenih upita. Valjda. Prvo sracunam sve moguce kombinacije Obveznika i Konta koje se pojavljuju, pa onda treba da racunam kamate za svaku od njih. Ovi ugnjezdeni upiti su kao for each u C#.
E sad, treba da limitiram set podataka unutrasnjeg upita tako da odgovaraju samo onima iz spoljasnjeg. Tu WHERE i GROUP BY nista ne pomazu, jedva ukapirah. Moram WHERE unutar FROM, ili bi eventualno mogao da dodam jos dva uporedivanja t1.Obveznik = Data.Obveznik i t1.Konto = t2.Konto onome t1.Datum_dospijeca > Data.Datum_dospijeca. To je ono sto si pricao da ORDER BY nema uticaja na rezultat upita, jel?
Od resenja sa WITH sam odma odusta, ta klauzula mora valjda bit van svih ugnjezdavanja.
Evo kako sam probao:
Code:
SELECT DISTINCT Obveznik, Konto,
(
SELECT SUM(Kamata) FROM
(
SELECT (SELECT(SUM(t.Duguje - t.Potrazuje)) AS Saldo FROM Data t WHERE t.Datum_dospijeca <= Data.Datum_dospijeca) * 0.0003 *
Coalesce(
DateDiff(
day,
Data.Datum_dospijeca,
(SELECT MIN(t1.Datum_dospijeca) FROM Data t1 WHERE t1.Datum_dospijeca > Data.Datum_dospijeca)
)
,0) AS Kamata
FROM
(
SELECT * FROM Data
WHERE Data.Obveznik = Spoljni.Obveznik AND Data.Konto = Spoljni.Konto
UNION (SELECT (SELECT MAX(ID)+1 FROM Data), Spoljni.Obveznik, Spoljni.Konto, Getdate(), Getdate(), 0, 0, 0)
) AS Data
) AS tmp
)
FROM Data AS Spoljni
Srednji SELECT je tu jer mi ne da da racunam tu sumu direktno u unutrasnjem upitu, kaze ne moze da racuna sumu nad poljem koje vec ima agregatnu f-ju ili ima korelisan upit. Ajde dobro.
Evo sta je rezultat ovog upita:
Code:
Obveznik Konto Kamata
------------------------------
1 1 -5.016
1 2 -1.905
A trebalo bi da bude ovo (kada dva puta odradim pojedinacni upit):
Code:
Obveznik Konto Kamata
------------------------------
1 1 -8.073
1 2 +7.9812
Sigurno alijasi prave problem, ali ne znam zasto mi to rade. Pogledaj molim te, ako budes imao kad.
Pozdrav i hvala.