更新存储过程中的聚合列

Update aggregate columns inside stored procedure

考虑在特定日期 call_date.

更新指定 phone_id 聚合数据的存储过程
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 andcall_date将作为参数传入。其他列应包含从另一个 table 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) 是所需的聚合。

类似这样的方法可能有效:

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

您是否需要保留应用更新前的值的任何记录?在这种情况下,我会改用插入和一个标志来将 number/date 的已经存在的事件标记为旧的。

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

如果聚合值已经由您插入 query.There 与单个列或聚合列之间没有区别 value.You 可以更新列 normally.Only 您应该考虑的是功能性列

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

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