【问题标题】:TSQL: Create row per period depending on start - end date based on existing rowsTSQL:根据开始-结束日期根据现有行创建每个期间的行
【发布时间】:2021-03-03 17:45:46
【问题描述】:

我有下表与汽车。人们有一辆标准汽车,但有时(当汽车进入车库或损坏时)他们会得到另一辆汽车。在我的国家,你必须为驾驶公司的汽车纳税,所以驾驶汽车的时间和驾驶的汽车很重要。如果备用车是更便宜的车,那么您在此期间缴纳的税款就更少。

表没那么难:

CREATE TABLE dbo.CARUSAGE
(
    ID int IDENTITY(1,1) NOT NULL,
    StartDate datetime NULL,
    EndDate datetime NULL,
    CarID int NULL,
    UserID int NULL,
    TypeID int NULL
);

INSERT dbo.CARUSAGE (StartDate, EndDate, CarID, UserID, TypeID) 
VALUES ('2020-04-19', NULL, 2, 2606, 1)
       ,('2020-07-07', '2020-10-07', 3, 2606, 2)
       ,('2020-10-12', '2020-10-31', 4, 2606, 2)

类型ID:
TypeID 1 = 标准。
TypeID 2 = 备用。

标准汽车就像一根线。除非您使用备用车,否则您始终拥有一辆标准车。

EndDate 标准汽车仍在行驶时为 NULL。

我喜欢实现这样的结果集:

+----------+--------+---------+---------+-------------+-------------+
|  NewID  |  CarID |  UserID |  TypeID |   StartDate |     EndDate |
+----------+--------+---------+---------+-------------+-------------+
|        1 |      2 |    2606 |       1 | 2020-04-19  | 2020-07-06  |
|        2 |      3 |    2606 |       2 | 2020-07-07  | 2020-10-06  |
|        3 |      2 |    2606 |       1 | 2020-10-07  | 2020-10-11  |
|        4 |      4 |    2606 |       2 | 2020-10-12  | 2020-10-30  |
|        5 |      2 |    2606 |       1 | 2020-10-31  | GetDate()   |
|          |        |         |         |             |             |
+----------+--------+---------+---------+-------------+-------------+

基于上述的附加问题:

虽然 GMB 很好地回答了我的问题,但我忘了提一件事,这使查询变得有点复杂。

可以添加新的“标准”汽车。当添加新的“标准”汽车时,原来的“标准”汽车就会有一个结束日期。源表如下所示:

INSERT dbo.CARUSAGE (StartDate, EndDate, CarID, UserID, TypeID) 
VALUES ('2020-04-19', '2020-11-04', 2, 2606, 1)
       ,('2020-07-07', '2020-10-07', 3, 2606, 2)
       ,('2020-10-12', '2020-10-31', 4, 2606, 2)
       ,('2020-11-05', null, 5, 2606, 1)
       ,('2020-11-09', '2020-11-14', 6, 2606, 2)

过程必须相同。 总是有一辆“标准”汽车。 选择结果将如下所示

+----------+--------+---------+---------+-------------+-------------+
|  NewID  |  CarID |  UserID |  TypeID |   StartDate |     EndDate |
+----------+--------+---------+---------+-------------+-------------+
|        1 |      2 |    2606 |       1 | 2020-04-19  | 2020-07-06  |
|        2 |      3 |    2606 |       2 | 2020-07-07  | 2020-10-06  |
|        3 |      2 |    2606 |       1 | 2020-10-07  | 2020-10-11  |
|        4 |      4 |    2606 |       2 | 2020-10-12  | 2020-10-30  |
|        5 |      2 |    2606 |       1 | 2020-10-31  | 2020-11-04  |
|        6 |      5 |    2606 |       1 | 2020-11-05  | 2020-11-08  |
|        7 |      6 |    2606 |       2 | 2020-11-09  | 2020-11-13  |
|        8 |      5 |    2606 |       1 | 2020-11-14  | GetDate()   |
+----------+--------+---------+---------+-------------+-------------+

提前致谢。

【问题讨论】:

  • 仅供参考,表格没有“记录”,它们有列和行,特定行中的特定列有值。

标签: sql-server date tsql datetime


【解决方案1】:

如果我没看错的话,你可以将开始日期和结束日期取消透视,并用备用记录填补“空白”,如下所示:

select t.carid, c.userid,t.typeid, t.dt as startdt,
    lead(dateadd(day, -1, t.dt), 1, convert(date, getdate())) over(partition by c.userid order by t.dt) as enddt
from carusage c
cross apply (select carid from carusage c1 where c1.userid = c.userid and c1.typeid = 1) s
cross apply (values (c.startdate, c.typeid, c.carid), (c.enddate, 1, s.carid)) t(dt, typeid, carid)
where t.dt is not null
order by t.dt

Demo on DB Fiddlde

卡里德 |用户名 |类型标识 |开始|结束 ----: | -----: | -----: | :------------------------ | :------------------------ 2 | 2606 | 1 | 2020-04-19 00:00:00.000 | 2020-07-06 00:00:00.000 3 | 2606 | 2 | 2020-07-07 00:00:00.000 | 2020-10-06 00:00:00.000 2 | 2606 | 1 | 2020-10-07 00:00:00.000 | 2020-10-11 00:00:00.000 4 | 2606 | 2 | 2020-10-12 00:00:00.000 | 2020-10-30 00:00:00.000 2 | 2606 | 1 | 2020-10-31 00:00:00.000 | 2020-11-20 00:00:00.000

【讨论】:

  • 您好专线小巴。你能看看我的问题的补充。看来你是唯一有答案的人。
猜你喜欢
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多