DevProTalk

DevProTalk (http://www.devprotalk.com/index.php)
-   SQL baze podataka - Sponzor: Baze-Podataka.net (http://www.devprotalk.com/forumdisplay.php?f=10)
-   -   I'm too old for this **** [last 24 hrs distribution query] (http://www.devprotalk.com/showthread.php?t=10910)

dee 28. 03. 2012. 20:02

I'm too old for this **** [last 24 hrs distribution query]
 
ne znam jesam li umoran il sta je, al nikako ne mogu nabost neko elegantno rjesenje...pa ako nekome pada stogod napamet, bit cu vrlo zahvalan...

u bazu biljezim podatak X(int) svaku minutu i to na nacin da upisujem samo ako se razlikuje od prethodne minute. dakle, moze biti zapisa svaku minutu, a moze ih ne biti satima.
treba mi query koji vraca MAX(X) za posljednja 24 sata (po satima).

za 24 sata u nekom danu jos i mogu izvuci (dakle, kad krece sa 0 i zavrsava s 23) medjutim dio kad krece sa npr 16 (jer u 16 sati covjek pokrene report) i zavrsi sa 15) - nikako nabost nesto lijepo.

meni treba TSQL ali to nije toliko vazno...i opisna ideja je i vise nego dosta.

Hvala!

jablan 28. 03. 2012. 21:18

http://sqlfiddle.com/#!1/a32c6/3

Edit: sad videh da ti je problem da počneš od npr. 15-og sata. Možeš to rešiti tako što ćeš u tabelu hours dodati još 24 sata, početi od npr. 15-og i koristiti "LIMIT 24".

Evo:

http://sqlfiddle.com/#!1/479c1/3

BraMom 29. 03. 2012. 11:36

Trebalo bi da može i ovako (TSQL):

Kôd:

SELECT       
        DATEPART(HH, TimeColumn) AS Hour,
        MAX(X) as MaxX
FROM
        [Table]
WHERE
        TimeColumn > DATEADD(DD, -1, GETDATE())
GROUP BY
        DATEPART(HH, TimeColumn)

Ako je bitan i redosled, kad kreće od 16 sati, da ide redom 16,17... pa sledeći dan, onda može ovako:

Kôd:

SELECT       
        MAX(DATEPART(DD, TimeColumn)) AS Day,
        DATEPART(HH, TimeColumn) AS Hour,
        MAX(X) as MaxX
FROM
        [Table]
WHERE
        TimeColumn > DATEADD(DD, -1, GETDATE())
GROUP BY
        DATEPART(HH, TimeColumn)
ORDER BY
        Day, Hour


dee 29. 03. 2012. 14:17

Citat:

Originalno napisao jablan (Napišite 106040)
http://sqlfiddle.com/#!1/a32c6/3

Edit: sad videh da ti je problem da počneš od npr. 15-og sata. Možeš to rešiti tako što ćeš u tabelu hours dodati još 24 sata, početi od npr. 15-og i koristiti "LIMIT 24".

Evo:

http://sqlfiddle.com/#!1/479c1/3

Ovo mi nije palo na pamet sa duplom tabelom sati pa da se uzima odredjeni range. Dobra fora!

Ima jos nesto sto nisam naveo u inicijalnom postu, a to je da nakon sto se dobije redoslijed, sve null (prazne) recorde iz desne tabele (nakon left outer joina) treba popuniti sa zadnjom vrijednosti iz iste tabele koja nije null. dakle, ako je na 14-om satu naisao na null, onda mora ici do prvog ranijeg sata koji nije null i sve izmedju napuniti tom vrijednoscu. (to je posljedica cinjenice da u bazu biljezim samo promjene, a ne sve)

Moj pristup je bio malo drugaciji.
- tmp tabela sa kolonama Sat, Vrijednost i identity autoincrement kolonom
- u nju prvo upisem sat/vrijednost za sve zapise u posljednjih 24 sata kojima je HOUR(timestamp) veci od HOUR(Current_Date) (to su jucerasnji)
- nakon toga upisem sve kojima je hour manji od trenutnog (danasnji)
- nadjem pocetnu vrijednost rangea posljednjih 24 sata (ako je prvi null ide u proslost dok ne nadje prvi koji nije null)
- na kraju CURSOR da popuni praznine

Ovaj dio s CURSOROM mi nije drag, rado bih to rijesio deklarativno, ali nakon 2 sata razmisljanja i probavanja nisam uspio i rijesio sam ipak s CURSOROM. Vidjet cemo kako ce se ponasat (setovi nisu nikad preveliki tako da ne bi trebalo igrat neku ulogu u performansama)

Ako ce nekome trebat, moje TSQL rjesenje je:

[@UserSubscriptionId je ulazni parametar u proceduru]
Kôd:

declare @currentHour int
set @currentHour = DATEPART(HOUR, getdate())

CREATE TABLE #HoursDistribution
(
        Id int IDENTITY(1, 1),
        Hr int,
        Value int
)

INSERT INTO #HoursDistribution
(
        Hr,
        Value
)

SELECT hrs.Hour, Entries.mNum
FROM [Hours] hrs
LEFT OUTER JOIN
                        (
                                SELECT DATEPART(HOUR, [Date]) AS Hr, MAX(NewMessagesNumber) AS mNum
                                FROM NewMessagesHistory
                                WHERE Date >= DateAdd(hh, -24, GETDATE())
                                AND UserSubscriptionId = @UserSubscriptionId
                                GROUP BY DATEPART(HOUR, [Date])
                        ) Entries
                        ON hrs.Hour = Entries.Hr
WHERE hrs.Hour > @currentHour

INSERT INTO #HoursDistribution
(
        Hr,
        Value
)

SELECT hrs.Hour, Entries.mNum
FROM [Hours] hrs
LEFT OUTER JOIN
                        (
                                SELECT DATEPART(HOUR, [Date]) AS Hr, MAX(NewMessagesNumber) AS mNum
                                FROM NewMessagesHistory
                                WHERE Date >= DateAdd(hh, -24, GETDATE())
                                AND UserSubscriptionId = @UserSubscriptionId
                                GROUP BY DATEPART(HOUR, [Date])
                        ) Entries
                        ON hrs.Hour = Entries.Hr
WHERE hrs.Hour <= @currentHour


DECLARE @LastV int
SELECT TOP 1 @LastV = MAX(NewMessagesNumber)
                                FROM NewMessagesHistory
                                WHERE Date < DateAdd(hh, -24, GETDATE())
                                AND UserSubscriptionId = @UserSubscriptionId
                                GROUP BY Id,DATEPART(HOUR, [Date])
                                ORDER BY Id DESC

IF @LastV IS NULL
BEGIN
        update #HoursDistribution
        set Value = 0
        where Id = 1
END
ELSE
BEGIN
        update #HoursDistribution
        set Value = @LastV
        where Id = 1
END

DECLARE @LastValue int
DECLARE Stavke_Cursor CURSOR FOR
SELECT
Id,
Hr,
Value

FROM #HoursDistribution

OPEN Stavke_Cursor
       
        DECLARE @Idt int
        DECLARE @Hrt int
        DECLARE @Valuet int
       
        FETCH NEXT FROM Stavke_Cursor
        INTO @Idt, @Hrt, @Valuet
       
        WHILE @@FETCH_STATUS = 0
        BEGIN

                IF @Valuet IS NOT NULL
                BEGIN
                        SET @LastValue = @Valuet
                END
               
                IF @Valuet IS NULL
                BEGIN
                        UPDATE #HoursDistribution
                        SET Value = @LastValue
                        WHERE Id = @Idt
                END
       
                FETCH NEXT FROM Stavke_Cursor
                INTO @Idt, @Hrt, @Valuet

        END

CLOSE Stavke_Cursor
DEALLOCATE Stavke_Cursor

SELECT * FROM #HoursDistribution
DROP TABLE #HoursDistribution


Svakako, puno hvala!

dee 29. 03. 2012. 14:19

Citat:

Originalno napisao BraMom (Napišite 106060)
Trebalo bi da može i ovako (TSQL):

Kôd:

SELECT       
        DATEPART(HH, TimeColumn) AS Hour,
        MAX(X) as MaxX
FROM
        [Table]
WHERE
        TimeColumn > DATEADD(DD, -1, GETDATE())
GROUP BY
        DATEPART(HH, TimeColumn)

Ako je bitan i redosled, kad kreće od 16 sati, da ide redom 16,17... pa sledeći dan, onda može ovako:

Kôd:

SELECT       
        MAX(DATEPART(DD, TimeColumn)) AS Day,
        DATEPART(HH, TimeColumn) AS Hour,
        MAX(X) as MaxX
FROM
        [Table]
WHERE
        TimeColumn > DATEADD(DD, -1, GETDATE())
GROUP BY
        DATEPART(HH, TimeColumn)
ORDER BY
        Day, Hour


Hmm...cini mi se da ovo nece radit ako u tabeli nema zapisa za danasnji dan (sto je sasvim realan slucaj ako u proslih 24 sata nije bilo promjene vrijednosti). Zato je, kako je i kolega jablan napisao, nuzna dodatna tabela u kojoj se drze sati (samo int upisi 0-23 [ili 1-24]) i s kojom se tabela zapisa left outer joina.

BraMom 29. 03. 2012. 15:12

Jasno, neće vratiti vrednosti za sate koje nisi imao kao unose, to svakako moraš da "popuniš" nekako

Pričali smo na sličnu temu
http://www.devprotalk.com/showthread.php?t=10632

dee 29. 03. 2012. 15:27

Citat:

Originalno napisao BraMom (Napišite 106069)
Jasno, neće vratiti vrednosti za sate koje nisi imao kao unose, to svakako moraš da "popuniš" nekako

Mozda nisam bio dovoljno precizan kad sam postavljao uvodno pitanje. Ne bi bilo cudo, umor je vec odradio svoje.
U svakom slucaju, u bazu se biljezi vrijednost samo ako je doslo do promjene. To moze znaciti kontinuirani upisi svake minute proslih x sati medjutim isto tako moze znaciti da nema upisa 10 dana. Koji god slucaj bio - 'last24hours' report trazi upravo to: stanja po satima u zadnjih 24 sata. Tako da, svakako mi ti upisi trebaju, bilo ih fizicki u tabeli ili bili 'zakljuceni' na osnovi proslih vrijednosti.

(ovo pisem cisto ako ce netko kasnije citat, da ima kontekst koji mu moze bit eventualno koristan ako treba sto slicno)

Citat:

Originalno napisao BraMom (Napišite 106069)

Da, slicna stvar. Nisam naisao na taj topic dok sam trazio.
Hvala za link!

jablan 29. 03. 2012. 21:24

Citat:

Originalno napisao dee (Napišite 106064)
sve null (prazne) recorde iz desne tabele (nakon left outer joina) treba popuniti sa zadnjom vrijednosti iz iste tabele koja nije null.

Pogledaj ovde, mislim da lepo može da se primeni na tvoj problem:

http://jablan.radioni.ca/post/101288...sing-self-join

dee 29. 03. 2012. 21:33

Citat:

Originalno napisao jablan (Napišite 106083)
Pogledaj ovde, mislim da lepo može da se primeni na tvoj problem:

http://jablan.radioni.ca/post/101288...sing-self-join

Kôd:

select t1.date, t1.temp, t2.date, t3.date
from temperatures t1
left join temperatures t2 on t1.date > t2.date
left join temperatures t3 on t3 < t1 and t2 < t3
where t3.date is null
order by t1.date, t2.date, t3.date;

krenuo sam u smjeru self-joina ali ga nisam uspio nabost i na kraju 'prelomio' kursorom. iako, ne treba naravno spominjat, koliko je ruzno proceduralno pisat stvari u SQLu.
Mislim da je ovo rjesenje, svakako cu ga probat.

Tnx!


Vreme je GMT +2. Trenutno vreme je 22:15.

Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.

Mišljenja, saveti, izjave, ponude ili druge informacije ili sadržaji nastali na Sajtu su vlasništvo onoga ko ih je kreirao, a ne DevProTalk.com, tako da ne morate da se oslanjate na njih.
Autori poruka su jedini odgovorni za ovakve sadržaje. DevProTalk.com ne garantuje tačnost, kompletnost ili upotrebnu vrednost informacija, stavova, saveta ili datih izjava. Ne postoje uslovi pod kojima bi mi bili odgovorni za štetu ili gubitak koji je posledica bilo čijeg oslanjanja na nepouzdane informacije, ili bilo kakve informacije nastale kroz komunikaciju između registrovanih članova.
Web sajt može sadržavati linkove na druge web sajtove na Internetu ili neke druge sadržaje. Ne kontrolišemo niti podržavamo te druge web sajtove, niti smo pregledali bilo kakve sadržaje na takvim sajtovima. Mi nećemo biti odgovorni za legalnost, tačnost ili prikladnost bilo kog sadržaja, oglasa, proizvoda, usluga ili informacije lociranim na ili distribuiranih kroz druge web sajtove, niti za bilo kakvu štetu nastalu kao posledica takvih informacija. DevProTalk.com drži i čuva druga prava vlasništva na web sajtu. Web sajt sadrže materijale zaštićene copyright-om, zaštitne znakove i druge informacije o pravu vlasništva ili softver. Članovi mogu poslatu informacije zaštićene pravima vlasništva njihovih nosilaca i ona ostaju zaštićena bez obzira da li su oni koji prenose te informacije to naveli ili ne. Osim informacija koje su u javnom vlasništvu ili za koje dobijete dozvolu, nemate pravo da kopirate, modifikujete ili na bilo koji način menjate, objavljujete, prenosite, distribuirate, izvršavate, prikazujete ili prodajte bilo koju informaciju zaštićenu pravima vlasništva. Slanjem informacija ili sadržaja na bilo koji deo DevProTalk.com, Vi automatski dozvoljavate i predstavljate garanciju da imate pravo da dozvolite DevProTalk.com ili članovima DevProTalk.com bespovratnu, kontinualnu, neograničenu, globalnu dozvolu da koriste, kopiraju, izvršavaju, prikazuju i distribuiraju takve informacije i sadržaje i da iz takvih sadžaja koriste bilo koji deo u bilo koje svrhe, kao i pravo i dozvolu da koriste gore navedene sadržaje. Svi zaštitni znakovi (trademarks), logotipi, oznake usluga, firme ili imena proizvoda koji se pominju na ovom web sajtu su vlasništvo kojim raspolažu njihovi vlasnici.