更新存储过程中的聚合列
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 and
call_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
考虑在特定日期 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 and
call_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