Avatar billede bosteen Nybegynder
10. juli 2004 - 09:51 Der er 6 kommentarer og
1 løsning

Summer kolonne og hent samtidig alle rækker

Jeg har brug for de enkelte rækker i en tabel, men samtidigt skal jeg bruge summen af en kolonne

Det har jeg løst ved at lade viewet køre det samme script to gange - men det må kunne gøres bedre
(hvis man kan nøjes med at køre script'et én gang og der trække alle oplysningerne, ville performance lige pludselig bive den dobbelte)

Scriptet er:

select
    -- Alle rækkerne
    LK.Period,
    LK.CostCenter,
    LK.Customer,
    LK.LeverancerUge,
    LKi.SumLeverancerUge,
    LK.LeverancerUge/LKi.SumLeverancerUge as Andel
from
    abc.dbo.Vw_T10_LeverancerKunde LK
inner join
    (
    -- Summering af leverancer uge
    select
        Period,
        CostCenter,
        sum(LeverancerUge) as SumLeverancerUge
    from
        abc.dbo.Vw_T10_LeverancerKunde
    group by
        Period,
        CostCenter
    ) LKi
on
    LK.Period = LKi.Period and LK.CostCenter = LKi.CostCenter
where
    LK.CostCenter = '0075'
    and LK.Period = '2004-04'

Eksempel på output:
Period, CostCenter, Customer, LeverancerUge, SumLeverancerUge, Andel
2004-04, 0075, 1111, 1.0, 100, 0.01
2004-04, 0075, 1112, 2.0, 100, 0.02
Avatar billede knowit-mmp Nybegynder
10. juli 2004 - 10:15 #1
Et forslag kunne være at bruge en nestet sætning, men jeg tvivler på at perfomance vil blive meget bedre bedre :

select
    -- Alle rækkerne
    LK.Period,
    LK.CostCenter,
    LK.Customer,
    LK.LeverancerUge,
-- Nestet select     
(select sum(LeverancerUge)
    from abc.dbo.Vw_T10_LeverancerKunde WHERE
        CostCenter=LK.CostCenter and Period=LK.Period) as SumLeveranceUge,
--Slut nestet select
    LK.LeverancerUge/SumLeverancerUge as Andel
from
    abc.dbo.Vw_T10_LeverancerKunde LK
where
    LK.CostCenter = '0075'
    and LK.Period = '2004-04'
Avatar billede bosteen Nybegynder
11. juli 2004 - 10:40 #2
Forslaget giver en kortere sql, men forbedrer desværre ikke performance. Desuden får jeg problemer, hvis jeg forsøger at linke til andre tabeller samtidigt:

select
    PS.CostCenter,
    PS.Period,
    PS.Customer, -- Leveringskundenr
    LK.LeverancerUge, -- Antal ugentlige leverancer pr. kundenr
    (
    select
        sum(LeverancerUge)
    from
        abc.dbo.Vw_T10_LeverancerKunde
    where
        cast(CostCenter as int) = PS.CostCenter
        and Period = PS.Period
        and cast(Customer as int) = cast(PS.Customer as int)
    ) as SumLeveranceUge
from
    dbo.Tbl_TOS_ProductionStatistics PS
left outer join
    dbo.Vw_T10_LeverancerKunde LK
on
    PS.CostCenter = cast(LK.CostCenter as int)
    and cast(PS.Customer as int) = cast(LK.Customer as int)
    and PS.Period = LK.Period
where
    action = '4' -- Dvs. tøjet er udscannet
    and PS.CostCenter in (75)
    and PS.Period in ('2004-04')

Her tager den tilsyneladende ikke hensyn til min nederste where sætning inde i "Nestet select" (og jeg kan ikke skrive kriterierne ind i "nestet select" where sætningen, da de skal trækkes et helt tredje sted fra, når den engang er færdig)
Avatar billede janus_007 Nybegynder
11. juli 2004 - 20:00 #3
Det kaldes en correlated subquery og ikke en nested select ;O)

Anyway... Jeg vil gætte på du kan opnå en bedre performance ved at arbejde med en temporær tabel. SQLserveren har svært ved at lave en ordentlig queryplan med subqueries - Det har jeg imidlertidigt erfaret nogle gange. Jeg formoder at den laver en total gruppering af data i subqueryen ligegyldigt hvad der stå i where clausen, men det kan du evt. tjekke selv i execution planen.

Prøv istedet:
select
        Period,
        CostCenter,
        sum(LeverancerUge) as SumLeverancerUge
into #sumtable
    from
        abc.dbo.Vw_T10_LeverancerKunde
    group by
        Period,
        CostCenter

og:
select
    -- Alle rækkerne
    LK.Period,
    LK.CostCenter,
    LK.Customer,
    LK.LeverancerUge,
    LKi.SumLeverancerUge,
    LK.LeverancerUge/LKi.SumLeverancerUge as Andel
from
    abc.dbo.Vw_T10_LeverancerKunde LK
inner join #sumtable LKi
on
    LK.Period = LKi.Period and LK.CostCenter = LKi.CostCenter
where
    LK.CostCenter = '0075'
    and LK.Period = '2004-04'
Avatar billede bosteen Nybegynder
12. juli 2004 - 14:21 #4
Jeg vil helst undgå at skulle lave ekstra tabeller, selvom det vil lette performance en del - men tak for input - det kan være jeg må acceptere, at der skal køres et ekstra loop i queryen
Avatar billede janus_007 Nybegynder
12. juli 2004 - 14:33 #5
Det er en temporær tabel og altså en helt normal måde at selecte data på. Den knytter sig kun til selve processen, lige så snart processen er færdig er tabellen væk.

SQLserveren opretter selv temporære tabeller konstant til diverse aggregat funktioner osv.
Avatar billede bosteen Nybegynder
12. juli 2004 - 14:47 #6
ok - det var smart :-)
Avatar billede janus_007 Nybegynder
12. juli 2004 - 16:04 #7
Jeps det er skide smart.

#tabelnavn betyder at tabellen kun er tilgængelig i den pågældende process altså lokalt

##tabelnavn betyder at tabellen kan nås fra andre processer også, altså globalt, men den termineres så bare i det øjeblik hvor selve processen der har oprettet den også lukker ned.
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