Avatar billede anri Novice
02. november 2013 - 10:28 Der 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.
Avatar billede cas000q1 Nybegynder
02. november 2013 - 10:44 #1
$result = mysqli_query($con,"SELECT * FROM ???");

while($row = mysqli_fetch_array($result))
  {
$totalværdi = $totalværdi+$row['værdi']
  }
echo $totalværdi;
//Sådanne:)
Avatar billede anri Novice
02. november 2013 - 10:55 #2
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.

Så det er desværre ikke svaret på mit spørgsmål.
Avatar billede anri Novice
02. november 2013 - 11:13 #3
Her er svaret :

select t1.id, t1.SomeNumt, SUM(t2.SomeNumt) as sum
from t1
inner join t2 on t1.id >= t2.id
group by t1.id, t1.SomeNumt
order by t1.id

Ordet jeg manglede for at kunne google det, var "culmulative", så er der jo eksempler nok derude.
02. november 2013 - 11:21 #4
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:

$result = mssql_query("SELECT * FROM ????");
while($row = mssql_fetch_array($result))
{
    $totalværdi = $totalværdi+$row['Værdi'];
    echo $row['Dato'] . " " . $row['Værdi'];
}
Avatar billede anri Novice
02. november 2013 - 12:02 #5
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.
02. november 2013 - 12:42 #6
Hvad var så svaret?  Hvis du mener jeg er gal på den, så lad mig lære med.
Avatar billede anri Novice
02. november 2013 - 15:33 #7
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).
02. november 2013 - 16:17 #8
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.
Avatar billede anri Novice
02. november 2013 - 16:30 #9
Det er da bestemt weekend :-)

SQL queryen havde jeg også lagt ind i #3:

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
Avatar billede Syska Mester
03. november 2013 - 01:14 #10
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.
Avatar billede anri Novice
04. november 2013 - 09:20 #11
Ja ok.
Den pointe kan jeg godt se.
En rekrusiv query på 1000 poster kan måske håndteres mere effektivt i applikationen.

Jeg får helt lyst til at lave forsøget bare for testens skyld.
Avatar billede Syska Mester
04. november 2013 - 19:30 #12
Hvis vi så igen kun snakker 1000 posts er det jo ingen ting.

1 mill vil i hvert fald kræve en test.

1000 posts er jo heller ikke specielt meget data.

20 bytes per row ... måske endda sat højt. 20Kbyte

Men hvis du laver testen så hører jeg gerne om det. Har ikke lige data til at teste det og heller ikke tiden.

mvh
Avatar billede anri Novice
04. november 2013 - 21:16 #13
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.
Avatar billede Syska Mester
04. november 2013 - 23:09 #14
45k rows Persons
10 millioner Dates.

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.

Jeg vil løbe hurtigt VÆK ...
04. november 2013 - 23:09 #15
(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?
Avatar billede anri Novice
04. november 2013 - 23:24 #16
Ja jeg kan så godt se at det ser ud til at være langt det mest effektive at beregne summen i appen. Buzzz, har du et index på datoerne?
Avatar billede Syska Mester
04. november 2013 - 23:51 #17
Da der bliver joinet på PersonId, Date har jeg et compound index på de columns.

Query analyseren siger også at det som tager tid er at slå de mange data op ... udover det så er der det rekursive join som er utroligt dyrt.

Når den så er færdig skal den til at sortere det hele ... og derefter regne på et UFATTELIGT stort dataset.

De 46200 rows bliver til 16193100 rows den skal group og sum på.

Hvis det er små data grundlag ... dvs 20 rows for en person ... fint. Men hvis det potentielt kan blive stort ... så lad være med at gøre det i DB'en.

Men tænker stadig det må kunne gøre med LAG i MSSQL 2012.

mvh
Avatar billede anri Novice
05. november 2013 - 08:31 #18
Ja, mine egne tests viser det samme.

Heldigvis kan jeg filtrere posterne ned til at blive max 365 rows inden jeg skal lave mine groups, så det tager ikke mange milisekunder.

..men den teoretiske diskussion gav mig da et lidt andet perspektiv på hele min opfattelse af hvornår jeg skal flytte operationer ud af SQL serveren.
Avatar billede Syska Mester
05. november 2013 - 08:39 #19
Super ...

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.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester