SQL Server 2008 выбирает данные только между месяцем и годом - PullRequest
0 голосов
/ 27 октября 2011

Я хотел бы выбрать данные между двумя датами, без дня

Пример ввода:

месяц начала: 9, год начала: 2011
последний месяц: 3, последний год: 2012

Я думаю, что есть два способа сделать это.

Первый - конвертировать начальный месяц и начальный год в дату, например 2011-09-01, и конвертировать последнюю дату в 2012-03-31, но для этого требуется вычислить последний день месяца окончания. Получив эти данные, мы можем использовать функцию BEETWEN для предложения WHERE (но надежна ли функция CONVERT?)

Второе решение - использовать функцию DATEPART, как показано в следующем коде:

Я пытаюсь объяснить: если конечный год равен начальному году, то месяц должен быть между начальным и конечным месяцами; иначе, если последние месяцы больше начальных, если они отличаются от начального и последнего года, я беру все промежуточное; иначе, если последний год, месяц должен быть меньше или равен последнему месяцу, если начальный год, месяц должен быть больше или равен последнему месяцу

Можете ли вы помочь мне сделать это наилучшим образом? Это правильно, решение я принял?

declare @IndDebitoCredito bit,@ProgTributo int,@mi as integer,@ai as integer,@mf as integer,@af as integer,@IDAnagrafica varchar(5)
select @mi = 01,@ai = 2011,@mf = 12,@af = 2011,@IDAnagrafica = 'DELEL',@IndDebitoCredito = 1
select distinct rrd.IDTributo
    from TBWH_Delega d
    --inner join TBWH_SezioneDelega sd on d.IDDelega = sd.IDDelega
    inner join TBWH_Rigo rd on rd.IDDelega = d.IDDelega
    inner join TBWH_RataRigo rrd on rrd.IDRigo = rd.IDRigo 
    where
    (
        DATEPART(MM,d.DataDelega)<=@mf and 
        DATEPART(MM,d.DataDelega)>=@mi and 
        DATEPART(YYYY,d.DataDelega)=@ai and 
        @af = @ai
    ) 
    OR
    (
        --anno finale magg. anno iniziale
        @af > @ai AND
        ( 
            (   -- delega nell'intervallo
                DATEPART(YYYY,d.DataDelega)<@af AND 
                DATEPART(YYYY,d.DataDelega)>@ai
                -- DATEPART(MM,d.DataDelega)>=@mi 
            )
            OR
            (   -- delega limite destro
                DATEPART(YYYY,d.DataDelega)=@af AND 
                DATEPART(MM,d.DataDelega)<=@mf 
            )
            OR
            (   -- delega limite sinistro
                DATEPART(YYYY,d.DataDelega)=@ai AND 
                DATEPART(MM,d.DataDelega)>=@mi 
            )
        )
    )

GO

Ответы [ 5 ]

2 голосов
/ 27 октября 2011

Ваше первое решение почти готово, но оно более сложное, чем должно быть, и не будет работать в любом случае.Он пропустит все строки последнего дня последнего месяца.

Вы можете добавить один месяц к end month и затем использовать BETWEEN в первый день каждого месяца.например.

start month: 9 , start year: 2011 end month: 3, end year: 2012

BETWEEN '2011-09-01' AND '2012-04-01'

или, как указывает JNK, это будет лучше:

DataDelega >= '2011-09-01' AND DataDelega < '2012-04-01'

Вам нужно будет добавить некоторую логику, чтобы иметь дело с end month в декабре, но это выглядит как самый простой способ сделать это.

1 голос
/ 27 октября 2011

Вы WAY усложняете это.Вам действительно нужно только два сравнения:

  • Являются ли месяц и год после или равны начальному значению?
  • Являются ли месяц и год до или равны окончательному значению?

Попробуйте:

SELECT *
FROM MyTable
WHERE Datefield BETWEEN 
     CAST(@mi as varchar) + '/1/' + CAST(@ai as varchar) 
     -- first of first month
     AND
     DATEADD(DAY, -1, (DATEADD(Month, + 1, (CAST(@mf as varchar) + '/1/' + CAST(@af as varchar))))) 
     -- Last day or final month
0 голосов
/ 27 октября 2011
DECLARE @mi INT
  , @ai INT
  , @mf INT
  , @af INT
SELECT  @mi = 01
      , @ai = 2011
      , @mf = 12
      , @af = 2011

--local variables to hold dates
DECLARE @i DATETIME
  , @f DATETIME

--build strings to represent dates in YYYYMMDD format
--add a month to the @f date
SELECT  @i = CONVERT(VARCHAR(4), @ai) + RIGHT('0' + CONVERT(VARCHAR(2), @mi),
                                              2) + '01'
      , @f = DATEADD(month, 1,
                     CONVERT(VARCHAR(4), @af) + RIGHT('0'
                                                      + CONVERT(VARCHAR(2), @mf),
                                                      2) + '01')

--select data where date >= @i, and < @f
SELECT  *
FROM    MyTable
WHERE   DateField >= @i
        AND DateField < @f 
0 голосов
/ 27 октября 2011

Я бы использовал:

WHERE DateToCheck >=               --- first day of StartMonth
          DATEADD( mm, @StartMonth-1,
                   DATEADD( yy, @StartYear-2000, '2000-01-01') 
                 )
  AND DateToCheck <                --- first day of next month (after EndMonth)
          DATEADD( mm, @EndMonth,
                   DATEADD( yy, @EndYear-2000, '2000-01-01') 
                 )
0 голосов
/ 27 октября 2011
SELECT *
  FROM Table
 WHERE DateField
       BETWEEN CONVERT(DATE, CONVERT(CHAR(4), @ai) + RIGHT('00' + CONVERT(VARCHAR(2), @mi), 2) + '01', 112)
           AND DATEADD(DD, -1, DATEADD(MM, 1, CONVERT(DATE, CONVERT(CHAR(4), @af) + RIGHT('00' + CONVERT(VARCHAR(2), @mf), 2) + '01', 112)))

Избегайте использования выражений в столбцах DateField, так как это делает запрос не SARGable .

...