Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL:如何计算可能重叠的日期范围之间的唯一天数?_Sql_Sql Server 2008_Date - Fatal编程技术网

SQL:如何计算可能重叠的日期范围之间的唯一天数?

SQL:如何计算可能重叠的日期范围之间的唯一天数?,sql,sql-server-2008,date,Sql,Sql Server 2008,Date,我有一个棘手的问题。我有一个社会保障缴款表,如下所示 每行代表个人的作业。个人可以同时从事一项以上的工作。我需要计算每个人在某一特定时期内的供款天数,例如在去年,问题是我必须只计算不同的供款天数,而不能对同一天的供款次数进行多次计算。我怎样才能做到这一点 列出可能的解决方案以计算天数,但不是唯一的 1-定义日期范围,这是一个计算人员贡献的时间窗口。 2-对于每个响应ID,我必须计算在此期间输入窗口有多少不同的天数 DECLARE @FchRef DATETIME SET @FchRef ='2

我有一个棘手的问题。我有一个社会保障缴款表,如下所示

每行代表个人的作业。个人可以同时从事一项以上的工作。我需要计算每个人在某一特定时期内的供款天数,例如在去年,问题是我必须只计算不同的供款天数,而不能对同一天的供款次数进行多次计算。我怎样才能做到这一点

列出可能的解决方案以计算天数,但不是唯一的 1-定义日期范围,这是一个计算人员贡献的时间窗口。 2-对于每个响应ID,我必须计算在此期间输入窗口有多少不同的天数

DECLARE @FchRef DATETIME

SET @FchRef ='2011-05-01'

--Fhc referencia de comienzo del programa a partir de cual calcular aportes
DECLARE @PeriRef SMALLINT

SET @PeriRef =24

--Periodo a partir de la Fch ref para contar aportes
DECLARE @FchCotDesde DATETIME

SET @FchCotDesde=Dateadd(MONTH, -24, @FchRef)

--Fch a partir de la cual calcular aportes
SELECT ut.documento                 'CI_UT',
       sum(DATEDIFF(DAY, CASE
                           WHEN CONVERT(DATETIME, act.fecha_ingreso, 103) < @FchCotDesde THEN @FchCotDesde
                           ELSE CONVERT(DATETIME, act.fecha_ingreso, 103)
                         END, CASE
                                WHEN fecha_egreso = '' THEN @FchRef
                                ELSE CONVERT(DATETIME, act.fecha_egreso, 103)
                              END)) 'DiasContados'
FROM   dbo.[UT2011_12] ut
       LEFT JOIN dbo.DatosPersonalesyDomicilios dat
         ON cast(cast(ut.documento AS DECIMAL(12, 0))AS VARCHAR) = dat.nro_documento
       LEFT JOIN dbo.Actividades act
         ON act.pers_identificador = dat.pers_identificador
            AND ( CONVERT(DATETIME, act.fecha_egreso, 103) = ''
                   OR CONVERT(DATETIME, act.fecha_egreso, 103) >= @FchCotDesde )
            -- La Fch de egreso es vacia ó con Fch posterior a fch ref
            AND CONVERT(DATETIME, act.fecha_ingreso, 103) <= @FchRef
--La Fch de inicio de act es anterior a la FchRef
WHERE  ut.UT_2011_Inscriptos = 1
        OR ut.UT_2012_Inscriptos = 1
GROUP  BY ut.documento 
我认为最好的办法是用一个图形来解决这个问题

111111111111111111111111111000000000000000000000000000000000000000000000000000000000
|----A1----|
         |----A2----|
               |----A3----|

00000111111111111111110000001111111111111111111111111000000000000000000000000000000
     |------B1-------|
                            |----------B2-----------|

最简单的方法可能是创建一个辅助日期表

CREATE TABLE Dates(D DATE PRIMARY KEY)

/*
Load dates between 1990-01-01 and 2049-12-31*/
INSERT INTO Dates
SELECT TOP (21915) DATEADD(DAY,ROW_NUMBER() OVER (ORDER BY (SELECT 1)), '19891231')
         AS N
   FROM master..spt_values v1,
        master..spt_values v2;
那你就可以了

DECLARE @FchRef DATE = '20110501';
DECLARE @FchCotDesde DATE = DATEADD(MONTH, -24, @FchRef);

SELECT [IdPersona],
       COUNT(DISTINCT Dates.D) AS Contributions
FROM Contributions  
JOIN Dates ON Dates.D BETWEEN fecha_ingreso AND fecha_egreso
WHERE Dates.D BETWEEN DATEADD(MONTH, -24, @FchRef) AND @FchRef
GROUP BY IdPersona

尝试以下方法。首先需要创建一个数字函数

create FUNCTION [dbo].[NumberTable] (@Min int, @Max int)
RETURNS @T TABLE (Number int NOT NULL PRIMARY KEY)
AS
BEGIN
INSERT @T VALUES (@Min)
WHILE @@ROWCOUNT > 0
BEGIN
INSERT @T
SELECT t.Number + (x.MaxNumber - @Min + 1)
FROM @T t
CROSS JOIN (SELECT MaxNumber = MAX(Number) FROM @T) x --Current max
WHERE
t.Number <= @Max - (x.MaxNumber - @Min + 1)
END
RETURN
END
然后,我所做的是循环作业,获取日期从和日期到值,并插入之间的所有日期

 Declare @Dates table
(UserId int,
DayDate datetime
)

 create table #aux(id int identity(1,1),
        Idpersona int
        ,FechaIngreso datetime
        ,FechaEgreso  datetime
        ) 
    insert into #aux values(5690180,'1987/1/1','2012/11/30')
    insert into #aux values(5690180,'2010/1/1','2012/11/30')
    insert into #aux values(5690180,'2012/6/11','2012/11/15')
    insert into #aux values(5690180,'2012/4/12','2012/4/25')
    insert into #aux values(5690180,'2012/3/16','2012/3/30')
    insert into #aux values(5690180,'2011/6/18','2011/10/15')
    insert into #aux values(5690180,'2012/12/20','2013/1/20')
    insert into #aux values(5690180,'2012/11/21','2012/12/15')

    declare @counter int
    select @counter = 1 
 WHILE @counter <= (Select COUNT(*) from #aux)
    Begin

        declare @User int
        select @User = Idpersona from #aux where id = @counter

        declare @YearMonthDayFrom datetime
        declare @YearMonthDayTo datetime
        select @YearMonthDayFrom = FechaIngreso from #aux where id = @counter
        select @YearMonthDayTo= FechaEgreso from #aux where id = @counter

        Declare @DateDifference int
        select @DateDifference = datediff(day, @YearMonthDayFrom,  @YearMonthDayTo) 

        insert into @Dates 
        select @User,
         dateadd(day,number,  @YearMonthDayFrom) 
        from
        dbo.NumberTable(0,@DateDifference)

        select @counter = @counter + 1
    end

   select year(daydate) as PeriodGroup,
    UserId, 
    COUNT(distinct DayDate)
   from @Dates
   group by UserId,
   year(daydate)

   drop table #aux

最后,我计算不同的天数,在我的示例中,我按年份分组。

+1 por la lengua Castellano您使用的是什么RDBMS?Oracle 11g、SQL Server 2008、,etc@MartinSmith我同意这个问题已经结束了。至于它的价值,op问他如何计算一个人进行交易的不同天数。问题是,日期之间的范围可能会重叠。这一信息适用于社会保障缴款。每行代表个人的作业。个人可能有一份以上的工作。所以我想计算一下有多少天实现了个人贡献,例如在去年的移动。问题是我必须用贡献计算不同的天数,而不是求和天数。入口=1/1/2010,出口=1/1/2010算零天还是一天?我在格式化SQL时遇到问题。当我在drop table aux下使用结束标记时,一半的代码消失了。我遗漏了什么吗?我没有使用工具栏上的按钮来设置代码格式。我现在觉得很好。你还看到这个问题吗?如果是的话,你是在Ipad上吗?这是一个可滚动的div。你需要用两个手指拖动它来查看其余的代码。现在看起来很好-我在我的电脑上,但由于某种原因无法正确地获取它。谢谢@EAguirre您遇到了什么问题?如果我没有理解错的话,没有@EAguirre,因为FechaIngreso是DateTime,当您插入'1987/1/1'时,它相当于1987年1月1日。当我在临时表aux中看到处理前的结果时,值是正确的。谢谢Martin,这是一个非常复杂问题的简单解决方案。fecha_有一个小细节,可以为空。但这很容易理解handling@EAguirre-这是否意味着他们仍在那里工作?如果是这样的话,那么GETDATE应该做。谢谢你,马丁,在这个例子中应该是ISNULLfecha_egreeso,@FchRef
create FUNCTION [dbo].[NumberTable] (@Min int, @Max int)
RETURNS @T TABLE (Number int NOT NULL PRIMARY KEY)
AS
BEGIN
INSERT @T VALUES (@Min)
WHILE @@ROWCOUNT > 0
BEGIN
INSERT @T
SELECT t.Number + (x.MaxNumber - @Min + 1)
FROM @T t
CROSS JOIN (SELECT MaxNumber = MAX(Number) FROM @T) x --Current max
WHERE
t.Number <= @Max - (x.MaxNumber - @Min + 1)
END
RETURN
END
 Declare @Dates table
(UserId int,
DayDate datetime
)

 create table #aux(id int identity(1,1),
        Idpersona int
        ,FechaIngreso datetime
        ,FechaEgreso  datetime
        ) 
    insert into #aux values(5690180,'1987/1/1','2012/11/30')
    insert into #aux values(5690180,'2010/1/1','2012/11/30')
    insert into #aux values(5690180,'2012/6/11','2012/11/15')
    insert into #aux values(5690180,'2012/4/12','2012/4/25')
    insert into #aux values(5690180,'2012/3/16','2012/3/30')
    insert into #aux values(5690180,'2011/6/18','2011/10/15')
    insert into #aux values(5690180,'2012/12/20','2013/1/20')
    insert into #aux values(5690180,'2012/11/21','2012/12/15')

    declare @counter int
    select @counter = 1 
 WHILE @counter <= (Select COUNT(*) from #aux)
    Begin

        declare @User int
        select @User = Idpersona from #aux where id = @counter

        declare @YearMonthDayFrom datetime
        declare @YearMonthDayTo datetime
        select @YearMonthDayFrom = FechaIngreso from #aux where id = @counter
        select @YearMonthDayTo= FechaEgreso from #aux where id = @counter

        Declare @DateDifference int
        select @DateDifference = datediff(day, @YearMonthDayFrom,  @YearMonthDayTo) 

        insert into @Dates 
        select @User,
         dateadd(day,number,  @YearMonthDayFrom) 
        from
        dbo.NumberTable(0,@DateDifference)

        select @counter = @counter + 1
    end

   select year(daydate) as PeriodGroup,
    UserId, 
    COUNT(distinct DayDate)
   from @Dates
   group by UserId,
   year(daydate)

   drop table #aux