Проблема с простым запросом выбора для поиска дат в SQL Server - PullRequest
3 голосов
/ 09 марта 2010

Я использую простой запрос, чтобы получить даты контракта для человека:

SELECT 
    [KlienciUmowyDataPoczatkowa],
    IsNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3

Вот что я получаю:

KlienciUmowyDataPoczatkowa  KlienciUmowyDataKoncowa
2005-11-28 00:00:00.000    2008-07-22 00:00:00.000
2008-07-23 00:00:00.000    2010-03-09 15:45:42.457

Клиент подписывает контракт, который начался в 2005-11-28, а затем было подписано приложение, поэтому его текущий контракт закончился в 2008-07-22, а новый - в 2008-07-23 и действует до сегодняшнего дня (NULL, который был преобразован в Текущее время). Могут быть клиенты со многими другими приложениями, но все так.

My question is: Как я могу получить контракт, который был / был активен между скажем 2008-04-01 - 2008-06-30? Возможно, что клиент между этими периодами будет иметь 2 или даже 5 приложений, поэтому он должен вернуть их все.

Также я не уверен, нужно ли использовать IsNull? Возможно, есть лучший способ для этого, чтобы я мог пропустить использование IsNull и ввести текущую дату в качестве замены.

РЕДАКТИРОВАТЬ:

Я думал, что решение от marc_s решило его, но, похоже, это не так:

SELECT 
    [KlienciUmowyDataPoczatkowa],
    [KlienciUmowyDataKoncowa]
FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
 WHERE  [PortfelID] = 3 AND 
 [KlienciUmowyDataPoczatkowa] <= '2008-07-01' AND IsNULL([KlienciUmowyDataKoncowa], '99991231') >= '2008-09-30'

Возвращает 0 дат за период с 2008-07-01 по 2008-09-30, когда должны возвращаться оба:

2005-11-28 00:00:00.000    2008-07-22 00:00:00.000
2008-07-23 00:00:00.000    NULL

Поскольку у клиента был контракт в оба раза.

EDIT2:

Я протестировал предложенные 2 запроса. Первый для дат (20080401 - 20080630), как в примере ниже, возвращает 1 строку для 1-го запроса (ожидается), возвращает 0 строк для 2-го запроса (не ожидается).

 SELECT [KlienciUmowyDataPoczatkowa],
    IsNULL([KlienciUmowyDataKoncowa], '99991231') AS 'KlienciUmowyDataKoncowa'
  FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]     
  WHERE  [PortfelID] = 3  
  AND [KlienciUmowyDataPoczatkowa] <= '20080401' AND IsNULL([KlienciUmowyDataKoncowa], '99991231') >= '20080630'

 SELECT 
 [KlienciUmowyDataPoczatkowa],
 [KlienciUmowyDataKoncowa]
 FROM   
[BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
 WHERE  
[PortfelID] = 3 AND 
-- either: start date is sometime between the two dates
([KlienciUmowyDataPoczatkowa] BETWEEN '20080401' AND '20080630'
-- or: end date is sometime between the two dates        
  OR 
  ISNULL([KlienciUmowyDataKoncowa], GETDATE()) BETWEEN '20080401' AND '20080630')

Второй тест для дат с '20080701' по '20080930' показывает для результатов первого запроса 0 (не ожидается) и для 2-го запроса 2 строки (ожидается).

 SELECT [KlienciUmowyDataPoczatkowa],
    IsNULL([KlienciUmowyDataKoncowa], '99991231') AS 'KlienciUmowyDataKoncowa'

 FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]

WHERE  [PortfelID] = 3  

 AND [KlienciUmowyDataPoczatkowa] <= '20080701' AND IsNULL([KlienciUmowyDataKoncowa], '99991231') >= '20080930'


SELECT 
[KlienciUmowyDataPoczatkowa],
[KlienciUmowyDataKoncowa]

FROM   
[BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  
[PortfelID] = 3 AND 
-- either: start date is sometime between the two dates
([KlienciUmowyDataPoczatkowa] BETWEEN '20080701' AND '20080930'
-- or: end date is sometime between the two dates        
  OR 
  ISNULL([KlienciUmowyDataKoncowa], GETDATE()) BETWEEN '20080701' AND '20080930')

EDIT3:

Используя решение COMBINED из обоих примеров, оно работает для обеих дат. Но не будет ли это ударом по мне для разных клиентов? Есть идеи?

 SELECT [KlienciUmowyDataPoczatkowa]
     , ISNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
 FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3
  AND 
  (
  ([KlienciUmowyDataPoczatkowa] BETWEEN '20080401' AND '20080630'
   OR ISNULL([KlienciUmowyDataKoncowa], GETDATE()) BETWEEN '20080401' AND '20080630')
   OR ([KlienciUmowyDataPoczatkowa] <= '20080401' AND IsNULL([KlienciUmowyDataKoncowa], '99991231') >= '20080630')

  )

SELECT [KlienciUmowyDataPoczatkowa]
 , ISNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
 FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3
  AND 
  (
  ([KlienciUmowyDataPoczatkowa] BETWEEN '20080701' AND '20080930'
   OR ISNULL([KlienciUmowyDataKoncowa], GETDATE()) BETWEEN '20080701' AND '20080930')
   OR ([KlienciUmowyDataPoczatkowa] <= '20080701' AND IsNULL([KlienciUmowyDataKoncowa], '99991231') >= '20080930')

  )

Ответы [ 4 ]

2 голосов
/ 09 марта 2010

Мой вопрос: как получить контракт? то есть / был активным между скажем 2008-04-01 - 2008-06-30? Возможно что клиент между этим периодом будет иметь 2 или даже 5 приложений, так что должен вернуть их все.

В основном это означает:

  • дата начала вашего контракта должна быть не позднее 2008-04-01
  • Дата окончания вашего контракта должна быть не позднее 2008-06-30

Так что вам нужно что-то вроде:

SELECT 
    (list of fields)
FROM dbo.YourTable
WHERE
    StartDate <= '20080401' AND EndDate >= '20080630'

(или как там будет по-польски: -)

Вам не понадобится ISNULL, если только одна из ваших дат не может быть NULL (например, EndDate = NULL означает: договор действителен до его аннулирования).

В этом случае сделайте что-то вроде:

SELECT 
    (list of fields)
FROM dbo.YourTable
WHERE
    StartDate <= '20080401' AND ISNULL(EndDate, '99991231') >= '20080630'

Если EndDate НЕДЕЙСТВИТЕЛЕН, представьте, что это 31 декабря 9999 года, что должно быть в течение следующих нескольких тысяч лет:)

UPDATE:
Для вашего обновления, попробуйте этот запрос здесь:

SELECT 
    [KlienciUmowyDataPoczatkowa],
    [KlienciUmowyDataKoncowa]
FROM   
    [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  
    [PortfelID] = 3 AND 
    -- either: start date is sometime between the two dates
    ([KlienciUmowyDataPoczatkowa] BETWEEN '20080701' AND '20080930'
    -- or: end date is sometime between the two dates        
      OR 
      ISNULL([KlienciUmowyDataKoncowa], GETDATE()) BETWEEN '20080701' AND '20080930')

Возвращает ли это ожидаемые результаты ??

1 голос
/ 09 марта 2010

Я думаю, это будет работать. Если нет, то можете ли вы быть немного более ясным и дать нам несколько примеров строк, которые должны и не должны быть возвращены.

SELECT 
    [KlienciUmowyDataPoczatkowa],
    IsNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3
AND KlienciUmowyDataPoczatkowa] <= '2008-04-01'
AND IsNULL([KlienciUmowyDataKoncowa], GETDATE()) >= '2008-06-30'

Или вы могли бы сделать

SELECT 
    [KlienciUmowyDataPoczatkowa],
    IsNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3
AND KlienciUmowyDataPoczatkowa] <= '2008-04-01'
AND ([KlienciUmowyDataKoncowa] >= '2008-06-30'
  OR [KlienciUmowyDataKoncowa] IS NULL)

Наконец, звучит так, что вы могли бы хотеть все контракты для клиентов, у которых был хотя бы 1 активный контракт между этими датами. Если это так, сделайте это:

SELECT 
    [KlienciUmowyDataPoczatkowa],
    IsNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3
AND <Client_ID> IN
    (SELECT 
        <Client_ID>
    FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
    WHERE  [PortfelID] = 3
    AND KlienciUmowyDataPoczatkowa] <= '2008-04-01'
    AND IsNULL([KlienciUmowyDataKoncowa], GETDATE()) >= '2008-06-30')
0 голосов
/ 09 марта 2010

Это должно получить все ваши строки, которые начинаются или заканчиваются в течение периода (обратите внимание на переменные @StartDate и @EndDate)

SELECT [KlienciUmowyDataPoczatkowa]
     , ISNULL([KlienciUmowyDataKoncowa], GETDATE()) AS 'KlienciUmowyDataKoncowa'
 FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy]
WHERE  [PortfelID] = 3
  AND ([KlienciUmowyDataPoczatkowa] BETWEEN @StartDate AND @EndDate
   OR ISNULL([KlienciUmowyDataKoncowa], GETDATE()) BETWEEN @StartDate AND @EndDate)
0 голосов
/ 09 марта 2010

Если я хорошо понимаю ваш вопрос, думаю, вы могли бы использовать что-то похожее на:

SELECT  
    [KlienciUmowyDataPoczatkowa], 
    CASE WHEN [KlienciUmowyDataKoncowa] IS NULL THEN GETDATE() ELSE [KlienciUmowyDataKoncowa] END AS 'KlienciUmowyDataKoncowa' 
FROM   [BazaZarzadzanie].[dbo].[KlienciPortfeleUmowy] 
WHERE  [PortfelID] = 3 
    AND [KlienciUmowyDataPoczatkowa] BETWEEN @ContractDateStart AND @ContractDateEnd

Где @ContractDateStart и @ContractDateEnd являются параметризованными значениями даты и конца контракта соответственно для вашего запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...