我有两个表,tblPrice 和 tblDiscount,每个表都有其值,其中包含 liveFrom 和 liveUntil 列(加上一些其他列,但我将这些列排除在外,以尝试使其更简单)。
我想做的是将价格和折扣列表显示为有序列表,它将显示价格如何根据价格变化或折扣变化而变化。
价格
行 | 价格ID | 零售价 | 来自 | 活到 |
---|---|---|---|---|
1 | 446413 | 1666.33 | 2022-01-31 11:36:21.490 | 2022-04-08 15:13:41.230 |
2 | 1338193 | 1666.33 | 2022-04-09 09:30:14.043 | 2023-04-05 09:37:21.767 |
3 | 2707357 | 1749.65 | 2023-04-05 09:37:21.767 | 空 |
tbl折扣
行 | 日志ID | 折扣 | 来自 | 活到 |
---|---|---|---|---|
1 | 192 | 0.3700 | 2022-01-31 11:27:45.060 | 2023-01-09 14:32:24.413 |
2 | 498 | 0.3200 | 2023-01-09 14:32:24.413 | 2023-04-11 15:40:06.460 |
3 | 639 | 0.3100 | 2023-04-11 15:40:06.460 | 空 |
预期结果
行 | 零售价 | 折扣 | 来自 | 活到 |
---|---|---|---|---|
1 | 1666.33 | 0.37 | 2022年1月31日11:36 | 2022年8月4日15:13 |
2 | 1666.33 | 0.37 | 2022年9月4日09:30 | 2023年9月1日14:32 |
3 | 1666.33 | 0.32 | 2023年9月1日14:32 | 2023年5月4日09:37 |
4 | 1749.65 | 0.32 | 2023年5月4日09:37 | 2023年4月11日15:40 |
5 | 1749.65 | 0.317 | 2023年4月11日15:40 | 空 |
需要注意的是:
我尝试根据日期范围将表相互连接,然后使用 case 语句来显示实时起始日期和实时截止日期,但它似乎不太正确,我只是无法完全理解逻辑。结果并没有如我所愿,我觉得我正朝着错误的方向掉进兔子洞。
到目前为止我的查询(正如我所说,我不确定这是正确的方法)是:
SELECT
P.[priceID],
P.[retailPrice],
P.[liveFrom],
P.[liveUntil],
D.[logID],
D.[discount],
D.[liveFrom],
D.[liveUntil],
------------
CASE
WHEN SDV.[liveFrom] <= P.[liveFrom] AND (SDV.[liveUntil] >= P.[liveFrom] OR SDV.[liveUntil] IS NULL) THEN
SDV.[liveFrom]
WHEN SDV.[liveFrom] >= P.[liveFrom] AND (SDV.[liveUntil] <= P.[liveUntil] OR P.[liveUntil] IS NULL) THEN
P.[liveFrom]
ELSE
'1900-01-01 00:00:00'
END AS [EFFECTIVE_FROM],
CASE
WHEN ISNULL(P.[liveUntil],@date) < ISNULL(SDV.[liveUntil],@date) THEN
P.[liveUntil]
ELSE
SDV.[liveUntil]
END AS [EFFECTIVE_UNTIL]
FROM
tblPrice P
INNER JOIN tblDiscount D ON P.[supplierDiscountID] = D.[supplierDiscountID]
AND ((
D.[liveFrom] <= P.[liveFrom]
AND (D.[liveUntil] >= P.[liveFrom] OR D.[liveUntil] IS NULL)
) OR
(
D.[liveFrom] >= P.[liveFrom]
AND (D.[liveFrom] <= P.[liveUntil] OR P.[liveUntil] IS NULL)
))
ORDER BY
P.[liveFrom],
D.[liveFrom];
我没有得到我想要的结果,而且我要走的路线似乎也不正确。有人可以给我任何指示或想法吗?
您必须查找在价格结束之前开始并在价格开始之后结束的折扣行,因此这可能是一种方法:
-- Sample data
declare @tblPrice table
( priceID int not null, retailPrice money not null
, liveFrom datetime not null, liveUntil datetime)
declare @tblDiscount table
( logID int not null, discount decimal(5,4) not null
, liveFrom datetime not null, liveUntil datetime)
insert into @tblPrice values
( 446413,1666.33,'2022-01-31T11:36:21.490','2022-04-08T15:13:41.230')
,(1338193,1666.33,'2022-04-09T09:30:14.043','2023-04-05T09:37:21.767')
,(2707357,1749.65,'2023-04-05T09:37:21.767', null)
insert into @tblDiscount values
(192, 0.37, '2022-01-31T11:27:45.060','2023-01-09T14:32:24.413')
,(498, 0.32, '2023-01-09T14:32:24.413','2023-04-11T15:40:06.460')
,(639, 0.317,'2023-04-11T15:40:06.460', null)
-- Prices with discounts available or without any discount
select P.retailPrice
, isNull(D.discount, 0) as discount
, case when P.liveFrom >= isNull(D.liveFrom, P.liveFrom)
then P.liveFrom
else D.liveFrom
end as liveFrom
, case when P.liveUntil <= isNull(D.liveUntil, P.liveUntil)
then P.liveUntil
else D.liveUntil
end as liveUntil
from @tblPrice P
left join @tblDiscount D on
-- P.supplierDiscountID = D.supplierDiscountID and
D.liveFrom <= isNull(P.liveUntil, getDate())
and P.liveFrom <= isNull(D.liveUntil, getDate())
union all
-- Prices that begins before 1st discount available
select x.retailPrice
, 0 as discount
, x.liveFrom
, x.lf as liveUntil
from (
select P.retailPrice, P.liveFrom
, min(D.liveFrom) lf
from @tblPrice P
left join @tblDiscount D on
-- P.supplierDiscountID = D.supplierDiscountID and
D.liveFrom <= isNull(P.liveUntil, getDate())
and P.liveFrom <= isNull(D.liveUntil, getDate())
group by P.priceID, P.retailPrice, P.liveFrom
having min(D.liveFrom)
> P.liveFrom
) x
union all
-- Prices that ends after last discount available
select x.retailPrice
, 0 as discount
, x.lu as liveFrom
, x.liveUntil
from (
select P.retailPrice, P.liveUntil
, max(isNull(D.liveUntil, getDate())) lu
from @tblPrice P
left join @tblDiscount D on
-- P.supplierDiscountID = D.supplierDiscountID and
D.liveFrom <= isNull(P.liveUntil, getDate())
and P.liveFrom <= isNull(D.liveUntil, getDate())
group by P.priceID, P.retailPrice, P.liveUntil
having max(isNull(D.liveUntil, getDate()))
< isNull(P.liveUntil, getDate())
) x
order by liveFrom