Avatar billede pluth Nybegynder
29. september 2010 - 19:39 Der er 12 kommentarer og
1 løsning

SQL beregning

Hej,

Jeg er i tvivl om hvordan jeg nemmest kan lave en løsning, og håber at i kan hjælpe med et bud.

Jeg har et total antal posteringer, som jeg ønsker at dele i 14 lige store dele. Af dem skal jeg finde ud af, hvor mange i hver portion der er indbetalinger.

Hvis der totalt er 100 posteringer, vil en portion være 7 afrundet (7,14) stk. Af dem er første portion måske 1 indbetaling. Næste portion er 2 osv.

Så jeg ender med et resultat, som siger

Indbetalinger=1,2,x,x,x,x,x,x,x,x,x,x,x,x

Kan det laves i en samlet SQL ?

//Antal
Select count(*) from posteringer

//Antal indbetalinger
Select count(*) from posteringer where type = 'indbetalinger' order by dato
Avatar billede janus_007 Nybegynder
29. september 2010 - 20:11 #1
Hvor skal du bruge resultatet?
Avatar billede pluth Nybegynder
29. september 2010 - 20:18 #2
I en rapport hvor det nogenlunde sådan ud

Indbetalinger=1,2,x,x,x,x,x,x,x,x,x,x,x,x

Så hvis det hele ikke kan laves i en SQL, så kan jeg godt lave nogle beregninger selv ved siden af.
Avatar billede HenrikSjang Nybegynder
29. september 2010 - 20:57 #3
Jeg har lavet et lille test-setup, hvor jeg har lavet en tabel der hedder Posteringer, og så indsætter jeg i alt 100 rækker med bit'en ErIndbetaling til 1, og opdaterer jeg 75 random rækker til at hedde ErIndbetaling 0.
Og så har jeg 2 forskellige udtræk, som giver dit ønskede resultat enten som et resultset med 14 rækker, eller som én kommasepareret streng.

Here goes:

--laver test tabel
create table Posteringer (
    id int identity,
    ErIndbetaling int
)

--Indsætter 100 rækker med ErIndbetaling = 1
insert into Posteringer (ErIndbetaling) values (1)
go 100

--Opdaterer 75 random rækker til at hedde ErIndbetaling = 0
update Posteringer
set ErIndbetaling = 0
where id in (
    select top 75 id from Posteringer
    order by checksum(newid())
)


--Denne giver dit ønskede resultat som et resultset med 14 rækker, hver med værdien for den tilhørende gruppe.
;WITH CTE AS (
    SELECT
        *,
        NTILE(14) OVER(ORDER BY id) AS Gruppe
    FROM Posteringer
)
SELECT Gruppe, (SELECT COUNT(*) FROM CTE t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe) AS AntalIndbetalinger
FROM CTE t1
GROUP BY Gruppe


--Denne giver dit ønskede resultat som en kommasepareret streng
;WITH CTE AS (
    SELECT
        *,
        NTILE(14) OVER(ORDER BY id) AS Gruppe
    FROM Posteringer
), CTE2 AS (
SELECT Gruppe, (SELECT COUNT(*) FROM cte t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe) AS AntalIndbetalinger
FROM cte t1
GROUP BY Gruppe
)
SELECT SUBSTRING(
    (SELECT ',' + CAST(AntalIndbetalinger AS VARCHAR(10)) FROM cte2
    FOR XML PATH('')),2,200000) AS CSV
Avatar billede pluth Nybegynder
29. september 2010 - 21:45 #4
Det ser ud til at virke 100% efter hensigten.. Jeg siger rigtig mange gange tak :)

Smid et svar.
Avatar billede HenrikSjang Nybegynder
30. september 2010 - 08:14 #5
Svar :)
Avatar billede pluth Nybegynder
30. september 2010 - 18:27 #6
Er det muligt, at det kan vises i procent af det samlede ? Kan ikke helt overskue hvor jeg skal gøre det ?
Avatar billede HenrikSjang Nybegynder
30. september 2010 - 20:39 #7
ja det tror jeg da, men jeg er ikke lige helt med på hvilke tal der skal stå som procent af det hele.

Hvis den første chunk er på 6 tal, og 2 af dem er indbetalinger, så vil det første tal der returneres være 2. Ønsker du at tallet der returneres i stedet er 33% ?

Eller er det procentsatsen af indbetalinger pr. chunk set mod det samlede antal indbetalinger for alle  chunks? Altså hvis strengen returnerer:

2,2,1,1

så skal det hedde 50%, 50%, 25%, 25% ??
Avatar billede pluth Nybegynder
30. september 2010 - 21:03 #8
Det er når der er 6 tal, og 2 af dem er indbetalinger, så er det 33% der returneres.

Det vil være rigtig fedt, hvis det kan lade sig gøre :)
Avatar billede HenrikSjang Nybegynder
30. september 2010 - 21:47 #9
Jeg skal nok lige se på det i morgen.

Hvad med afrunding? skal det være hele procent, fx 33%, eller skal der x decimaler efter kommaet? Og du vil gerne have %-tegnet med i output'et, altså så det er tekst der returneres i stedet for et tal ?
Avatar billede HenrikSjang Nybegynder
30. september 2010 - 22:04 #10
Nå, jeg fik lige kigget på det med det samme. De samme to queries som før har jeg modificeret. Jeg har antaget at du vil have værdien returneret som "50.0%". Hvis du ikke vil have decimalen med, eller måske vil have flere decimaler, så skal du bare finde det sted hvor jeg i koden laver en CAST til decimal(3,1) og rette til nogle andre værdier. 3 angiver antal tegn i tallet, og 1-tallet angiver hvor mange af disse der er efter kommaet.

--Denne giver dit ønskede resultat som et resultset med 14 rækker, hver med værdien for den tilhørende gruppe.
;WITH CTE AS (
    SELECT
        *,
        NTILE(14) OVER(ORDER BY id) AS Gruppe
    FROM Posteringer
)
SELECT
    Gruppe,
    COUNT(*) AS TotalAntal,
    (SELECT COUNT(*) FROM CTE t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe) AS AntalIndbetalinger,
    CAST(CAST((SELECT COUNT(*)*1.0 FROM CTE t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe)/COUNT(*)*100 AS decimal(3,1)) AS VARCHAR(10)) + '%' AS ProcentSats   
FROM CTE t1
GROUP BY Gruppe


--Denne giver dit ønskede resultat som en kommasepareret streng
;WITH CTE AS (
    SELECT
        *,
        NTILE(14) OVER(ORDER BY id) AS Gruppe
    FROM Posteringer
), CTE2 AS (
SELECT
    Gruppe,
    COUNT(*) AS TotalAntal,
    (SELECT COUNT(*) FROM cte t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe)*1.0 AS AntalIndbetalinger,
    CAST(CAST((SELECT COUNT(*)*1.0 FROM CTE t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe)/COUNT(*)*100 AS decimal(3,1)) AS VARCHAR(10)) + '%' AS ProcentSats   
FROM cte t1
GROUP BY Gruppe
)
SELECT SUBSTRING(
    (SELECT ',' + CAST((ProcentSats) AS VARCHAR(1000)) FROM cte2
    FOR XML PATH('')),2,200000) AS CSV
Avatar billede pluth Nybegynder
01. oktober 2010 - 07:14 #11
Tak for det - Jeg kan ikke teste det nu, men gør det senere.

Endnu engang tak for din store hjælp.
Avatar billede pluth Nybegynder
05. oktober 2010 - 18:25 #12
Jeg er desværre nød til at spørge efter hjælp en gang til :(

Jeg har en anden tabel, som indeholder alt tid forbrugt på de forskellige transaktioner. Hvis jeg ønsker at se hvor mange transaktioner jeg behandler hver time, hvordan kan jeg så få det vist i % (altså eks. er der 10 transaktioner i hver af de 14 perioder, som alle har taget 2 timer at udfører, så det giver 5,5,5,5,5,5,5,5,5,5,5,5,5,5)

Min tids tabel ser ud som "Select * from timer order by create"

Hvis du skal have flere point for at hjælpe må du endelig sige til. Håber meget at du vil hjælpe endnu en gang.
Avatar billede pluth Nybegynder
07. oktober 2010 - 08:08 #13
Jeg har prøvet dette, som jeg mener burde virke hvis jeg forstår SQL korrekt. Men den giver en fejl med gruppe

Håber der er en som kan give mig lidt hjælp ?

;WITH CTE AS (
    SELECT
        *,
        NTILE(14) OVER(ORDER BY create) AS Gruppe
    FROM timer
), CTE2 AS (
SELECT
    Gruppe,
    COUNT(*) AS TotalAntal,
    (SELECT COUNT(*) FROM posteringer t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe)*1.0 AS AntalIndbetalinger,
    CAST(CAST((SELECT COUNT(*)*1.0 FROM CTE t2 WHERE t2.ErIndbetaling = 1 AND t1.Gruppe = t2.Gruppe)/COUNT(*)*100 AS decimal(3,1)) AS VARCHAR(10)) AS ProcentSats   
FROM cte t1
GROUP BY Gruppe
)
SELECT SUBSTRING(
    (SELECT ',' + CAST((ProcentSats) AS VARCHAR(1000)) FROM cte2
    FOR XML PATH('')),2,200000) AS CSV
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