02. november 2013 - 10:28Der er
18 kommentarer og 1 løsning
Stable værdier pr. dato
Lad os antage at mine data ser således ud: Dato \ Værdi 1/1 \ 10 2/1 \ 8 3/1 \ 4 4/1 \ 6 5/1 \ 8 6/1 \ 4
Jeg skal have lavet en query der for hver dato, lægger alle værdier fra tidligere datoer sammen så output bliver således: 1/1 \ 10 2/1 \ 18 3/1 \ 22 4/1 \ 28 5/1 \ 36 6/1 \ 40
Nogen gode forslag? Jeg ved ikke hvor stort dato-spændet er, på forhånd.
Takker. Der er dog flere problemer med den løsning ;
Spørgsmålet ligger inde under MS SQL, så jeg kan ikke bruge MySql funktioner. Selve SQL syntaxen bør dog være det samme.
Du trækker resultatet over i PHP og laver din matematik der. Det bør være en funktion der kan varetages af SQL databasen så resultatsettet ikke bør efterbehandles.
Du laver EN samlet sum af resultaterne og ikke en kulmulativ sum, af alle tidligere datoer, for hver dato.
Jeg kender ikke nogen løsning direkte i mssql til at opsummere værdierne. Det er egenligt ikke database systemets opgave, men en opgave for applikationen, såsom i php.
Men i php vil jeg mene, at løsningen vil se således ud:
Tak for kommentaren. Jeg fandt selv et svar, men lad os lige kigge på din påstand om at det ikke bør ligge i databasen.
Jeg ved godt at det er et spørgsmål om preferencer, men lad os i dit eksempel antage at vi har en million poster vi skal summere. Databasen ligger ikke nødvendigvis på samme server som applikationen, så skal summeringen foregå i applikationen, skal vi først overføre de en million poster fra en computer til en anden og derefter lægge dem sammen.
Lægger vi dem sammen i databasen, bliver det kun et enkelt resultat vi skal returnere.
Svaret har jeg jo skrevet tidligere i denne tråd. ..men jeg må ha udtrykt mig for vagt, for den anden gut forstod også bare at jeg ville ha' en samlet sum for alle poster.
Altså din løsning, vil givetvis vide de tal jeg er efter, men da det jo er i MS SQL kategorien, er det et SQL resultatset jeg er efter (af samme grund som tidligere nævnt).
Det er muligvis min hjerne der er for vag til at følge dig - du opstillede et problem, og du sagde, at koden i #4 muligvis ville give det søgte resultat hvis man vil gøre det i php, men du ønskede resultatet direkte i mssql. Det fandt du så, ifølge #5, et svar på. Jeg er nysgerrig efter, hvordan du bar dig ad, og jeg håber du vil vise mig den kode/query du fandt frem til.
select t1.dato, t1.Vaerdi, SUM(t2.Vaerdi) as sum from t1 inner join t2 on t1.dato >= t2.dato group by t1.dato, t1.Vaerdi order by t1.dato
- - - - Den logiske problemstilling var: En lærer registrerer dagligt hvor mange timers fravær en elev har. Det kunne se sådan ud : 2, 1.5, 0, 0, 0, 0, 4
Jeg skal så vise en graf der viser et overblik over det samlede fravær pr dato. Hvis jeg bare viser de registrerede tal, så vil grafen gå op og ned, så derfor skal jeg summere hver datos fravær med alle de forrige dages fravær så listen ser således ud: 2, 3.5, 3.5, 3.5, 3.5, 3.5, 7.5
Det er faktisk et nasty fedt hack med join og datoen ... :-)
Men det CB henviste til var med at man ikke bør have logik i sin DB. Men er det et gammelt projekt kan det være svært at lave om på og så er dette jo en god løsning.
Performance for dette hvis du har 1 mill rows ... tror jeg stadig den er ringe og kan måske alligevel være hurtigere. Dog ikke noget jeg har testet, men MSSQL er ikke lavet til at regne på så mange rows alligevel.
Jeg er dog rimelig sikker på at MS måske har en løsning i SQL 2012 ... LAG og LEAD med en kombo af en CTE.
Ja de 1000000 rows er også for at sætte tingene lidt på spidsen. Der kommer jeg aldrig op, men nok en 90000 der skal sorteres i og så joines rekursivt. Og det er max.
select D1.Date, P.PersonId, D1.Value, SUM(D2.Value) as sum from Dates D1 INNER JOIN Persons P ON D1.PersonId = P.PersonId inner join Dates AS D2 ON D1.PersonId = D2.PersonId AND D1.Date >= D2.Date WHERE P.[Type] = 10 group by P.PersonId, D1.Date, D1.Value order by P.PersonId, D1.Date -- Tager 12 sek.
select D1.Date, D1.Value from Dates D1 INNER JOIN Persons P ON D1.PersonId = P.PersonId -- inner join Dates AS D2 ON D1.PersonId = D2.PersonId WHERE P.[Type] = 10 order by D1.PersonId, D1.Date -- Tager 0.350 sek.
Ergo er der 11½ sekunder til at regne på samme data i .NET.
Der er 199 personer med Type = 10.
Begge queries returnere 46200 rows. Ergo ... der bliver jo ikke færre rows.
(Først lige for at forklare min forvirring, jeg forvekslede #3 med #1, således at jeg antog #3 for at være den den kode der var foreslået af en anden og som du havde afvist. Beklager.)
Hvis du, i en php applikation, blot (for den pågældende elev) vil vise en række datoer og for hver dato det kumulative fravær (for så at bruge de kumulative tal til en graf), så er der vel ikke behov for nogen rekursiv query, blot en helt almindelig "SELECT * FROM mintabel WHERE .... ORDER BY dato". Så sendes hele molevitten fra databasen til applikationen som et enkelt resultat, som så kan indeholde op til 90000 rækker. Så går applikationen resultatet efter række for række og for hver række/dato beregner det kumulative fravær og skriver dette ud sammen med datoen med en kode efter princippet i #4. Sådan plejer jeg at gøre i lignende tilfælde, og det er vist nok gængs praksis. Eller har jeg misforstået problemstillingen?
Du skrev bare tidligere at der kunne være: 90000 rækker der skulle joines :-)
Men var faktisk også lidt sjovt for mig at lege med ... så jeg har også lært noget.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.