我有几种用法。一种是准备另一种是实际用法。
需要检查上一时期的预付费类型开始和结束日期是否等于下一个时期的(相等)开始和结束日期
期末,我已经准备好使用量,根据逻辑上,下期的使用量必须与上期的预付款匹配。但是有时候我会遇到这两种类型不匹配的情况。 例如
1 (128193 ,'2020-05-01', '2020-05-31','prepaid'),
2 (134145 ,'2020-06-01', '2020-06-30','prepaid'),
3 (134145 ,'2020-05-01', '2020-05-30','usage'),
示例记录编号3应与该期间的预付款记录编号1匹配,在这种情况下,它们使用在时间段134145中的开始和结束日期不等于预付款在上期128193中。
我需要找到那些情况。
我创建了一个脚本
DECLARE @t TABLE ( id INT, startdate DATE, enddate DATE , u_type VARCHAR(255))
INSERT INTO @t
VALUES ( 128193 ,'2020-05-01', '2020-05-31','prepaid'),
(134145 ,'2020-06-01', '2020-06-30','prepaid'),
(134145 ,'2020-05-01', '2020-05-30','usage'),
(141461 ,'2020-07-01', '2020-07-31','prepaid'),
(141461 ,'2020-06-01', '2020-06-30','usage');
WITH cte
AS ( SELECT ROW_NUMBER() OVER ( ORDER BY id ) AS r ,
id ,
startdate ,
enddate,
u_type
FROM @t
)
SELECT c2.id ,
c1.id,
c1.startdate,
c1.enddate,
c2.startdate,
c2.enddate,
c1.u_type,
c2.u_type
FROM cte c1
JOIN cte c2 ON c2.r + 1 = c1.r AND c2.u_type <> c1.u_type
WHERE DATEADD(d, 1, c2.enddate) <> c1.startdate
但是它会返回错误的结果。
这是一次运行,所以我不在乎性能速度是否可以使用#tables CTE所需的任何内容,以及有关如何解决它的任何想法?
预付款记录始终会在未来期间使用。
答案 0 :(得分:2)
DECLARE @t TABLE ( id INT, startdate DATE, enddate DATE , u_type VARCHAR(255))
INSERT INTO @t
VALUES ( 128193 ,'2020-05-01', '2020-05-31','prepaid'),
(134145 ,'2020-06-01', '2020-06-30','prepaid'),
(134145 ,'2020-05-01', '2020-05-30','usage'),
(141461 ,'2020-07-01', '2020-07-31','prepaid'),
(141461 ,'2020-06-01', '2020-06-30','usage');
WITH CTE_PERIOD_RANGE
AS (SELECT ID,
STARTDATE,
ENDDATE,
U_TYPE,
LEAD(STARTDATE, 1) OVER(PARTITION BY U_TYPE ORDER BY STARTDATE) AS NEXT_PERIOD_STARTDATE,
LEAD(ENDDATE, 1) OVER(PARTITION BY U_TYPE ORDER BY STARTDATE) AS NEXT_PERIOD_ENDDATE
FROM @t)
SELECT ID,
STARTDATE,
ENDDATE,
U_TYPE
FROM CTE_PERIOD_RANGE
WHERE STARTDATE <> NEXT_PERIOD_STARTDATE OR
ENDDATE <> NEXT_PERIOD_ENDDATE AND
NEXT_PERIOD_STARTDATE IS NOT NULL; -- this filters out the last occurrence of each type, because this record has no following period
这将返回:
╔════════╦════════════╦════════════╦═════════╗
║ id ║ startdate ║ enddate ║ u_type ║
╠════════╬════════════╬════════════╬═════════╣
║ 128193 ║ 2020-05-01 ║ 2020-05-31 ║ prepaid ║
║ 134145 ║ 2020-06-01 ║ 2020-06-30 ║ prepaid ║
║ 134145 ║ 2020-05-01 ║ 2020-05-30 ║ usage ║
╚════════╩════════════╩════════════╩═════════╝
请参见SQLFiddle:demo
答案 1 :(得分:1)
不是吗
select
p.id as p_id, u.id as u_id,
p.startdate as p_startdate, u.startdate as u_startdate,
p.enddate as p_enddate, u.enddate as u_enddate
from
@t u
inner join @t p
on(
p.u_type = 'prepaid'
--
and p.startdate <= u.enddate
and p.enddate >= u.startdate
)
where
u.u_type = 'usage'
--
and (
p.startdate <> u.startdate
or p.enddate <> u.enddate
)
我们寻找与prepaid
相匹配的usage
,然后检查其边界。