我有以下问题:
SELECT C.DateValue, T.CustomerId, T.Balance
FROM Calendar C
CROSS APPLY (
SELECT TOP(1) StartDate, CustomerId, Balance
FROM TestData B
WHERE B.StartDate <= C.DateValue
ORDER BY StartDate DESC
) AS T
WHERE C.DateValue BETWEEN '1/1/2014' AND '1/14/2014'
ORDER BY CustomerId, DateValue
这需要一组数据,例如:
CustomerId | StartDate | EndDate | Balance
123 | 1/1/2014 | 1/3/2014 | 2000
123 | 1/3/2014 | 1/10/2014 | 1000
123 | 1/10/2014 | null | 500
并将其转换为:
CustomerId | Date | Balance
123 | 1/1/2014 | 2000
123 | 1/2/2014 | 2000
123 | 1/3/2014 | 1000
123 | 1/4/2014 | 1000
123 | 1/5/2014 | 1000
...
我遇到的问题是它只有在有一个CustomerId时才有效。只要我在列表中添加另一个。我试图找到一种方法来改变这个查询,以支持数据集中任意数量的CustomerIds。我可以通过使用如下查询来完成此任务:
SELECT C.DateValue, T.CustomerId , T.Balance
FROM Calendar C
INNER JOIN TestData T on C.DateValue >= T.DataStartDate
AND (C.DateValue < T.EndDate OR T.EndDate IS NULL)
WHERE C.DateValue BETWEEN '1/1/2014' AND '1/14/2014'
但是当我将它加入到包含数百万客户的实际表中时,上述查询效率非常低。 如何更改查询或编写查询以实现将数据扩展到每日列表的目标?
答案 0 :(得分:2)
MS SQL Server 2012架构设置:
查询1 :
SELECT S.CustomerId, S.DateValue, T.Balance
FROM (
SELECT DISTINCT CustomerId, DateValue
FROM TestData, Calendar
WHERE DateValue BETWEEN '1/1/2014' AND '1/14/2014') S
CROSS APPLY (
SELECT TOP(1) Balance
FROM TestData B
WHERE B.StartDate <= S.DateValue AND B.CustomerId = S.CustomerId
ORDER BY StartDate DESC
) AS T
ORDER BY CustomerId, DateValue
<强> Results 强>:
| CUSTOMERID | DATEVALUE | BALANCE |
|------------|------------|---------|
| 123 | 2014-01-01 | 25000 |
| 123 | 2014-01-02 | 25000 |
| 123 | 2014-01-03 | 25000 |
| 123 | 2014-01-04 | 25000 |
| 123 | 2014-01-05 | 25000 |
| 123 | 2014-01-06 | 25000 |
| 123 | 2014-01-07 | 20000 |
| 123 | 2014-01-08 | 20000 |
| 123 | 2014-01-09 | 10000 |
| 123 | 2014-01-10 | 10000 |
| 123 | 2014-01-11 | 10000 |
| 123 | 2014-01-12 | 10000 |
| 123 | 2014-01-13 | 10000 |
| 123 | 2014-01-14 | 10000 |
| 456 | 2014-01-01 | 25000 |
| 456 | 2014-01-02 | 25000 |
| 456 | 2014-01-03 | 25000 |
| 456 | 2014-01-04 | 25000 |
| 456 | 2014-01-05 | 25000 |
| 456 | 2014-01-06 | 25000 |
| 456 | 2014-01-07 | 20000 |
| 456 | 2014-01-08 | 20000 |
| 456 | 2014-01-09 | 10000 |
| 456 | 2014-01-10 | 10000 |
| 456 | 2014-01-11 | 10000 |
| 456 | 2014-01-12 | 10000 |
| 456 | 2014-01-13 | 10000 |
| 456 | 2014-01-14 | 10000 |
答案 1 :(得分:0)
以下是我最终进行的查询:
SELECT C.DateValue, T.CustomerId, T.Balance
FROM Calendar C
CROSS APPLY (
SELECT B.CustomerId, B.Balance
FROM TestData B
WHERE C.DateValue >= B.StartDate AND (C.DateValue < B.EndDate OR B.EndDate IS NULL)
) AS T
WHERE C.DateValue BETWEEN '1/1/2014' AND '1/14/2014'
ORDER BY CustomerId, DateValue
@BogdanSahlean值得我指出正确的方向。关键是要确保WHERE
中的CROSS APPLY
条款已正确调整。