2

難しい問題があります。以下のような社会保障拠出金の表があります( SQL Fiddle )

    IdPersona   fecha_ingreso   fecha_egreso
5690180         01/01/1987      30/11/2012
5690180         01/01/2010      30/11/2012
5690180         11/06/2012      15/11/2012
5690180         12/04/2012      25/04/2012
5690180         16/03/2012      30/03/2012
5690180         18/06/2011      15/10/2011
5690180         20/12/2012      20/01/2013
5690180         21/11/2012      15/12/2012

各行は、個人の仕事を表します。個人は、同時に複数の仕事を持っている場合があります。昨年など、特定の期間に各個人が行った貢献の日数を数える必要があります。問題は、貢献の異なる日数のみを数えなければならず、個人に対して同じ日を複数回数えてはならないことです。どうすればこれを達成できますか?


日数をカウントするための可能な解決策を概説しますが、一意ではありません。2-RespondentID ごとに、この期間中に入力ウィンドウのある異なる日数を数えなければなりませんか?

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 

このソリューションの問題点は、日付範囲 (イングレスとイーグレス) が重なっている場合に機能することです。それは問題の解決策として私に起こりました: 1 - 各人を含むカーソルを作成します 2 - 毎日のウィンドウ期間をループするループを作成します。個人。私が提案するソリューションは非常に複雑です。より良い解決策を考えられますか?

このスクリプトを使用すると、テーブルを作成できます

        create table #aux(
        Idpersona int
        ,FechaIngreso datetime
        ,FechaEgreso  datetime
        ) 
    insert into #aux values(5690180,'1987/01/01','2012/11/30')
    insert into #aux values(5690180,'2010/01/01','2012/11/30')
    insert into #aux values(5690180,'2012/06/11','2012/11/15')
    insert into #aux values(5690180,'2012/04/12','2012/04/25')
    insert into #aux values(5690180,'2012/03/16','2012/03/30')
    insert into #aux values(5690180,'2011/06/18','2011/10/15')
    insert into #aux values(5690180,'2012/12/20','2013/01/20')
    insert into #aux values(5690180,'2012/11/21','2012/12/15')
    select * from #aux

問題を確認する良い方法は、1 つのグラフィックを使用することです

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

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

2 に答える 2

3

以下を試してください。最初に数値関数を作成する必要があります。

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

最後に、個別の日を数えます。この例では、年ごとにグループ化しています。

于 2013-06-12T21:40:29.117 に答える