我正在计算累积计数(两张表中的2条线索)。我设法得到以下结果。现在我想要像这样替换NULL值: 如果它是表的第一行,那么我需要插入第一个not null值。对于其余的行,我需要插入当前行之前的最后一个非null值。 是否有办法实现这一目标?
Date | Count1 | Count2
2016-01-01 00:00:00.000 | NULL | 52
2016-01-02 00:00:00.000 | NULL | 54
2016-01-05 00:00:00.000 | 62 | 55
2016-01-08 00:00:00.000 | NULL | 56
2016-01-11 00:00:00.000 | 91 | NULL
2016-01-12 00:00:00.000 | 92 | 59
通缉结果:
Date | Count1 | Count2
2016-01-01 00:00:00.000 | 62 | 52
2016-01-02 00:00:00.000 | 62 | 54
2016-01-05 00:00:00.000 | 62 | 55
2016-01-08 00:00:00.000 | 62 | 56
2016-01-11 00:00:00.000 | 91 | 56
2016-01-12 00:00:00.000 | 92 | 59
我用来生成此结果的查询:
declare @DateCountOpportunities table(d int primary key, c int, cr int)
insert into @DateCountOpportunities
select
datediff(d, 0, IsNull(CreationDate, StartDate)) as d,
count(*) as OpportunitiesCount,
0
from [JobOpportunities]
group by datediff(d, 0, IsNull(CreationDate, StartDate))
declare @rt int = 0
declare @anchor int
update @DateCountOpportunities set
@rt = cr = @rt + c,
@anchor = d
option (maxdop 1)
declare @DateCountRestaurants table(d int primary key, c int, cr int)
insert into @DateCountRestaurants
select
datediff(d, 0, CreatedAt) as d,
count(*) as RestaurantsCount,
0
from [Restaurants]
group by datediff(d, 0, CreatedAt)
declare @rtRes int = 0
declare @anchorRs int
update @DateCountRestaurants set
@rtRes = cr = @rtRes + c,
@anchorRs = d
option (maxdop 1)
Declare @ResultTable table(DateOpportunities DateTime, DateRestaurant DateTime, RestaurantsCount int, OpportunitiesCount int)
insert into @ResultTable
select isnull(DateOpportunities, DateRestaurants) DateOpportunities, isnull(DateRestaurants, DateOpportunities) DateRestaurant, RestaurantsCount, OpportunitiesCount from
(
select
dateadd(d, d, 0) as DateRestaurants,
cr as RestaurantsCount
from @DateCountRestaurants
) Rs
full outer join
(
select
dateadd(d, d, 0) as DateOpportunities,
cr as OpportunitiesCount
from @DateCountOpportunities
)Opp
on Rs.DateRestaurants = Opp.DateOpportunities
order by DateOpportunities
select DateOpportunities as [Date],
RestaurantsCount
,
OpportunitiesCount from @ResultTable
答案 0 :(得分:1)
这是一个匆忙的答案,但我希望它仍然有帮助。下面的查询将仅更新一列的所有记录,因此您可能需要重复第二列的逻辑。可能还有一种方法可以改变这种逻辑,以便它在同一个查询中处理Count1和Count2(即不需要多个UPDATE语句),但我现在还没有足够的时间来完成溶液
我已经测试了以下情况,其中NULL在第一行,中心行和最后一行成功:
CREATE TABLE #counting ( [Date] DATETIME, Count1 INT, Count2 INT )
INSERT INTO #counting
SELECT '2016-01-01', NULL, 52 UNION
SELECT '2016-01-02', NULL, 54 UNION
SELECT '2016-01-05', 62, 55 UNION
SELECT '2016-01-08', NULL, 56 UNION
SELECT '2016-01-11', 91, NULL UNION
SELECT '2016-01-12', 92, 59 UNION
SELECT '2016-01-13', NULL, 56
UPDATE
#counting
SET
Count1 = rangeValue
FROM
(
SELECT * FROM
(
SELECT TOP 1
firstDate,
firstValue.[Date] AS lastDate,
firstValue.Count1 AS rangeValue
FROM
#counting AS firstValue,
( SELECT MIN( [Date] ) AS firstDate FROM #counting WHERE Count1 IS NULL ) AS firstDate
WHERE
Count1 IS NOT NULL AND
firstDate < firstValue.[Date]
ORDER BY
[Date]
) AS a
UNION
SELECT
firstValueRecord.[Date] AS firstDate,
lastNullRecord.[Date] AS lastDate,
MAX( firstValueRecord.Count1 ) AS rangeValue
FROM
#counting AS firstValueRecord,
#counting AS nonNullRecords,
#counting AS lastNullRecord
WHERE
firstValueRecord.Count1 IS NOT NULL AND
nonNullRecords.Count1 IS NOT NULL AND
lastNullRecord.Count1 IS NULL AND
lastNullRecord.[Date] > nonNullRecords.[Date] AND
nonNullRecords.[Date] >= firstValueRecord.[Date]
GROUP BY
lastNullRecord.[Date],
firstValueRecord.[Date]
HAVING
COUNT(DISTINCT nonNullRecords.[Date]) = 1
) AS a
WHERE
Count1 IS NULL AND
[Date] BETWEEN firstDate AND lastDate
答案 1 :(得分:0)
从SQL Server 2012开始,我们可以使用SUM()OVER(... ORDER BY ...)
来计算运行总计。例如:
SELECT *, SUM(t.Amount) OVER(ORDER BY t.ActionDate) AS RunningTotal
FROM (VALUES
('2016-01-01 00:00:00.000', 62),
('2016-01-02 00:00:00.000', 0),
('2016-01-05 00:00:00.000', 0),
('2016-01-08 00:00:00.000', 0),
('2016-01-11 00:00:00.000', 29),
('2016-01-12 00:00:00.000', 0)
) t(ActionDate, Amount)
结果:
ActionDate Amount RunningTotal
----------------------- ----------- ------------
2016-01-01 00:00:00.000 62 62
2016-01-02 00:00:00.000 0 62
2016-01-05 00:00:00.000 0 62
2016-01-08 00:00:00.000 0 62
2016-01-11 00:00:00.000 29 91
2016-01-12 00:00:00.000 0 91
这意味着可以简化初始T-SQL批处理:
SELECT
ISNULL(b.ActionDate, d.ActionDate) AS ActionDate,
b.RunningTotal1,
d.RunningTotal2
FROM
(
SELECT b.ActionDate, SUM(b.Amount) OVER(ORDER BY b.ActionDate) AS RunningTotal1
FROM (
SELECT t.ActionDate, SUM(t.Amount) AS Amount
FROM dbo.FirstTable t
GROUP BY t.ActionDate
UNION ALL
SELECT DISTINCT t.ActionDate, NULL AS Amount
FROM dbo.SeconTable t
WHERE NOT EXISTS (SELECT * FROM dbo.FirstTable x WHERE x.ActionDate = t.ActionDate)
) a
) AS b
INNER JOIN
(
SELECT d.ActionDate, SUM(d.Amount) OVER(ORDER BY d.ActionDate) AS RunningTotal2
FROM (
SELECT DISTINCT t.ActionDate, NULL AS Amount
FROM dbo.FirstTable t
WHERE NOT EXISTS (SELECT * FROM dbo.SecondTable x WHERE x.ActionDate = t.ActionDate)
UNION ALL
SELECT t.ActionDate, SUM(t.Amount) AS Amount
FROM dbo.SeconTable t
GROUP BY t.ActionDate
) c
) AS d
ON b.ActionDate = d.ActionDate