【问题标题】:Horizontal date intervals to Vertical dates (possibly a sql/vba loop solution?)水平日期间隔到垂直日期(可能是 sql/vba 循环解决方案?)
【发布时间】:2017-06-20 08:05:46
【问题描述】:

是否有更快的方法将我的数据从 a - d 列作为人员信息,然后 e 列是休假开始日,f 列是休假结束日转换为以下数据:

列 a - d 在每一行上重复,列 e 是该范围内包含的每一天/日期的单独行?

目前,我正在手动执行此操作,以准备大量休假/在侦察中打卡。

我还应该补充一点,每一行都包含员工休假的时间间隔,并且同一员工可能在数据集中出现多次。

我正在阅读 SQL 脚本,尽管它似乎没有涵盖这种情况,需要为每个人创建这么多行和间隔。

【问题讨论】:

  • 您可以将数据导入到不可见的工作表中,而不是将其显示在第二个工作表中,在那里您可以使用公式指向第一个工作表中的正确数据。
  • 请显示表格结构/脚本和示例数据。还请展示您尝试过的示例。

标签: sql-server excel vba date intervals


【解决方案1】:

如果你想在 SQL 中解决这个问题,那么你可以使用日历或日期表来处理这类事情。

对于只有 152kb 的内存,您可以在一个表中包含 30 年的日期:

/* dates table */
declare @fromdate date = '20000101';
declare @years    int  = 30;
/* 30 years, 19 used data pages ~152kb in memory, ~264kb on disk */
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
select top (datediff(day, @fromdate,dateadd(year,@years,@fromdate)))
    [Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
into dbo.Dates
from n as deka cross join n as hecto cross join n as kilo
               cross join n as tenK  cross join n as hundredK
order by [Date];
create unique clustered index ix_dbo_Dates_date on dbo.Dates([Date]);

无需执行创建表的实际步骤,您就可以使用 common table expression 生成一个临时的日期表,只需这样做:

declare @fromdate date, @thrudate date;
select @fromdate = min(fromdate), @thrudate = max(thrudate) from dbo.leave;

;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
  select top (datediff(day, @fromdate, @thrudate)+1) 
      [Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
  from n as deka cross join n as hecto cross join n as kilo
                cross join n as tenK cross join n as hundredK
   order by [Date]
)

像这样使用:

/* `distinct` if there are overlaps or duplicates to remove */
select distinct 
    l.personid
  , d.[Date]
from dbo.leave l
  inner join dates d
    on d.date >= l.fromdate
   and d.date <= l.thrudate;

rextester 演示:http://rextester.com/AVOIN59493

来自这个测试数据:

create table leave (personid int, fromdate date, thrudate date)
insert into leave values
 (1,'20170101','20170107')
,(1,'20170104','20170106') -- overlapped 
,(1,'20170420','20170422') 
,(2,'20170207','20170207') -- single day 
,(2,'20170330','20170405')

返回:

+----------+------------+
| personid |    Date    |
+----------+------------+
|        1 | 2017-01-01 |
|        1 | 2017-01-02 |
|        1 | 2017-01-03 |
|        1 | 2017-01-04 |
|        1 | 2017-01-05 |
|        1 | 2017-01-06 |
|        1 | 2017-01-07 |
|        1 | 2017-04-20 |
|        1 | 2017-04-21 |
|        1 | 2017-04-22 |
|        2 | 2017-02-07 |
|        2 | 2017-03-30 |
|        2 | 2017-03-31 |
|        2 | 2017-04-01 |
|        2 | 2017-04-02 |
|        2 | 2017-04-03 |
|        2 | 2017-04-04 |
|        2 | 2017-04-05 |
+----------+------------+

数字和日历表参考:

【讨论】:

    【解决方案2】:

    伙计们,我如何解决这个问题实际上只是在这个论坛上使用了另一个公式,涉及到日期间隔的加入和之间。

    工作正常!

    考虑到周末和公共假期,Ps 将日历用于另一个关于实际工作日的场景......

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-30
      • 2020-12-26
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多