在sql server數(shù)據(jù)庫(kù)中求計(jì)算列和平均值

字號(hào):


    嚴(yán)格來(lái)說(shuō),having并不需要一個(gè)子表,但沒(méi)有子表的having并沒(méi)有實(shí)際意義。如果你只需要一個(gè)表,那么你可以用where子句達(dá)到一切目的。為進(jìn)行實(shí)踐,having預(yù)先假定至少兩個(gè)表和一個(gè)基于第二個(gè)表的合計(jì)函數(shù)。
    下面是一個(gè)簡(jiǎn)單的例子:你想要訂單總數(shù)超過(guò)25000美元的客戶(hù)清單。你需要適當(dāng)連接的三個(gè)表:customer、salesorderheader和salesorderdetail。然后,你求detail的和,并將總數(shù)與25000美元進(jìn)行比較。查看列表a。
    查看列表a中的代碼時(shí),有一件事情并不明顯,即linetotal列被計(jì)算。你可以像求實(shí)際的列的和一樣求出已計(jì)算列的和。但是,你不能在同一個(gè)操作中執(zhí)行兩個(gè)不同層次的合計(jì)函數(shù)。
    select
    sales.customer.customerid,
    sales.salesorderheader.salesorderid,
    sum(sales.salesorderdetail.linetotal)
    as subtotalfrom
    sales.customer
    inner join sales.salesorderheader
    on sales.salesorderheader.customer
    id = sales.customer.customerid
    inner join sales.salesorderdetail
    on sales.salesorderdetail.salesorder
    id = sales.salesorderheader.salesorderidgroup by
    sales.customer.customerid,
    sales.salesorderheader.salesorder
    idhaving sum(linetotal) > 25000.00order by
    sales.customer.customerid,
    salesorderid ;
    列表a:
    假設(shè)你希望知道所有客戶(hù)的平均銷(xiāo)售額。你可以使用列表b中的代碼,它返回如下錯(cuò)誤信息:
    select
    sales.salesorderheader.salesorderid,
    avg(sum(sales.salesorderdetail.linetotal))
    as averagefrom
    sales.salesorderheader
    inner join sales.salesorderdetail
    on sales.salesorderdetail.salesorder
    id = sales.salesorderheader.salesorder
    idgroup by
    sales.salesorderheader.salesorderid
    列表b:
    msg 130, level 15, state 1, line 1
    cannot perform an aggregate function on an expression
    containing an aggregate or a subquery.
    錯(cuò)誤信息:
    你可以將平均值的計(jì)算過(guò)程進(jìn)行分解來(lái)解決這個(gè)問(wèn)題。你可以將第一部分(sum)編寫(xiě)成一個(gè)表值udf,如列表c所示。你可以根據(jù)列表d中的函數(shù)計(jì)算平均值。列表e說(shuō)明你如何能夠進(jìn)行組合。
    use [adventureworks]
    go
    /****** object: userdefinedfunction
    [dbo].[salestotals_fnt]
    script date: 12/09/2006 11:32:54 ******/
    set ansi_nulls on
    go
    set quoted_identifier on
    go
    create function [dbo].[salestotals_fnt]()
    returns table
    as return
    (select salesorderid,
    sum(linetotal)as totalsale
    from sales.salesorderdetail
    group by sales.salesorderdetail.salesorderid)
    列表c:
    create function [dbo].[averagesale_fns] (
    -- add the parameters for the function here
    -- )returns money
    asbegin
    -- declare the return variable here
    declare @result money
    -- add the t-sql statements to compute the return value here
    set @result =(selectavg(totalsale)as averagesale
    from dbo.salestotals_fnt())
    -- return the result of the function
    return @result
    end
    列表d:
    declare @avg moneyselect @avg = dbo.averagesale_fns()
    select *, @avg as average,
    totalsale / @avg as ratio, case
    when totalsale / @avg > 1 then 'above average'
    when totalsale / @avg < 1 then 'below average'
    else 'average' end
    from dbo.salestotals_fnt()
    列表e:
    現(xiàn)在你知道了如何根據(jù)一個(gè)子表使用having子句來(lái)測(cè)試合計(jì)值。當(dāng)你需要在一個(gè)查詢(xún)中使用兩個(gè)不同的合計(jì)函數(shù)時(shí),最好是把它們分解成單獨(dú)的函數(shù),然后再進(jìn)行組合(如前一個(gè)例子所說(shuō)明的)。