更新存储过程中的聚合列

时间:2015-03-04 08:44:26

标签: sql-server tsql stored-procedures aggregate-functions

考虑在特定日phone_id更新指定call_date的汇总数据的存储过程。

create proc phone_calls_aggregate @phone_id int, @call_date date
as
begin
    -- check if aggregate table already exists
    if not exists (select * from sys.sysobjects 
                   where name = 'tbl_calls_agg')    
        create table tbl_calls_agg ( -- create table to store aggregate data
            phone_id int,
            call_date date,
            total_charge money,
            total_duration int
         )

     --update aggregate data
     update tbl_calls_agg 
     -- update aggregate columns
     where phone_id = @phone_id and call_date = @call_date
end
go

phone_id and call_date将作为参数传入。其他列应包含从另一个表tbl_calls.计算的汇总数据我可以在传统的UPDATE语句中更新这些列吗?

最初插入汇总数据的查询是:

select
    phone_id as [Phone Number], 
    call_date as [Call Date]     
    sum(charge) as [Total charge], 
    count(duration) as [Total Calls Duration]
from 
    tbl_calls
where 
    phone_id = @phone_id and call_date = @day
group by 
    phone_id, call_date

更具体地说,sum(charge)count(duration)是所需的聚合。

3 个答案:

答案 0 :(得分:1)

这样的事可能有用:

CREATE PROC phone_calls_aggregate @phone_id INT
    ,@call_date DATE
AS
BEGIN
    -- check if aggregate table already exists
    IF NOT EXISTS (
            SELECT *
            FROM sys.sysobjects
            WHERE NAME = 'tbl_calls_agg'
            )
        CREATE TABLE tbl_calls_agg (
            -- create table to store aggregate data
            phone_id INT
            ,call_date DATE
            ,total_charge MONEY
            ,total_duration INT
            )


    --update aggregate data
            ;

    WITH Agg_Data
    AS (
        SELECT phone_id AS [Phone Number]
            ,call_date AS [Call Date] sum(charge) AS [Total charge]
            ,count(duration) AS [Total Calls Duration]
        FROM tbl_calls
        WHERE phone_id = @phone_id
            AND call_date = @day
        GROUP BY phone_id
            ,call_date
        )


    UPDATE tbl
    SET total_charge = agg.[Total charge]
        ,total_duration = agg.[Total Calls Duration]
    FROM tbl_calls_agg tbl
    JOIN Agg_Data agg ON tbl.phone_id = agg.[Phone Number]
        AND tbl.call_date = agg.[Call Date]
END
GO

在应用更新之前,您是否需要保留任何值的记录?在这种情况下,我将使用insert而不是标记来标记已存在的数字/日期为旧的。

最后,你可能想要明确地考虑处理日期,因为它们在某些时候总是很痛苦。

答案 1 :(得分:1)

MERGE语句专为此类​​工作而设计:

CREATE PROCEDURE phone_calls_aggregate @phone_id int, @call_date date
AS
BEGIN

IF NOT EXISTS (SELECT * FROM sys.sysobjects 
               WHERE name = 'tbl_calls_agg')    
    CREATE TABLE tbl_calls_agg (
        phone_id INT,
        call_date DATE,
        total_charge MONEY,
        total_duration INT
     )

MERGE INTO tbl_calls_agg d
USING ( SELECT
            phone_id, 
            call_date     
            sum(charge) AS total_charge, 
            COUNT(duration) AS total_duration
        FROM tbl_calls
        WHERE phone_id = @phone_id AND call_date = @day
        GROUP BY phone_id, call_date
      ) s
ON d.phone_id = s.phone_id AND d.call_date = s.call_date
WHEN MATCHED AND (d.total_charge <> s.total_charge 
                  OR d.total_duration <> s.total_duration) THEN
    UPDATE SET d.total_charge = s.total_charge, d.total_duration = s.total_duration
WHEN NOT MATCHED BY TARGET THEN
    INSERT
    VALUES ( phone_id, call_date, total_charge, total_duration )
WHEN NOT MATCHED BY SOURCE THEN   
    DELETE;

END
GO

答案 2 :(得分:0)

如果您的查询已经插入了聚合值。具有单个或聚合值的列之间没有区别。您可以正常更新列。只考虑您应该具有的功能

update tbl_calls_agg 
     set total_charge=1000,
         total_duration=100
     where phone_id = @phone_id and call_date = @call_date