Как правильно соединить таблицу дат в T-SQL? - PullRequest
3 голосов
/ 14 мая 2011

Я сделал RIGHT JOINS в прошлом без проблем.Однако по какой-то причине сейчас я не могу успешно присоединиться к таблице дат в поле даты.В итоге у меня есть две таблицы.Первая таблица имеет один столбец даты и еще пару столбцов без даты.Затем у меня есть таблица дат, в которой просто есть два столбца дат.

Я инициализирую эту таблицу дат, вставляя в нее даты первого месяца в течение 13 последовательных месяцев.Но у моей другой таблицы есть только данные за 9 месяцев.

Таким образом, таблица A выглядит следующим образом:

col_A    col_B     col_C
-----    ------    -------
sfds     jkjlj     7-1-2009
rewr     sfsfsd    5-1-2009
xcxvg    sdfsfk    4-1-2009
...

Но таблица B выглядит следующим образом:

StartDate   EndDate
---------   ---------
7-1-2009    7-31-2009
6-1-2009    6-30-2009
5-1-2009    5-31-2009
...

Но когда я присоединяюсь к таблице B справа, A выглядит так:

    SELECT *
      FROM TABLE_A A
RIGHT JOIN TABLE_B B ON A.COL_C = B.StartDate

Я ожидаю получить данные за 12 месяцев, поскольку у Table_B 13 месяцев / записей.Однако вместо этого я получаю всего 9 месяцев.Кто-нибудь понимает, почему это будет?И другие вещи, которые я мог бы попытаться достичь того же результата?

Моя главная цель - включать Table_A каждый месяц в течение последних 13 месяцев, даже если есть нулевые значения.Хотя сейчас это всего лишь 9 месяцев, поскольку в течение остальных 4 месяцев не было записей.

Ответы [ 3 ]

8 голосов
/ 14 мая 2011

Присоединение к столбцам даты может быть проблематичным, если в датах есть часть времени (а это часто бывает!).

Безопаснее использовать DATEPART() или CONVERT() (или другие функции даты) для извлечения только части даты, но это, вероятно, исключит использование индексов.

Одним из способов является использование:

DATEADD(day, DATEDIFF(day, 0, DateColumn), 0)

1010 * т.е. *

SELECT *      
FROM TABLE_A A
RIGHT JOIN TABLE_B B ON 
   DATEADD(day, DATEDIFF(day, 0, A.COL_C), 0) = DATEADD(day, DATEDIFF(day, 0, B.StartDate), 0)

Существует также эта форма:

CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)

но я предпочитаю первое.

2 голосов
/ 14 мая 2011

Я только что попробовал это и получил все месяцы, столбцы col_A, col_B и col_C равны нулю, где не было совпадения.Вы уверены, что все ваши даты там, и нет оговорки, касающейся этого?

SELECT *
FROM TABLE_A A

sfds    jkjlj   2009-07-01 00:00:00.000


SELECT *
FROM TABLE_B B

2009-07-01 00:00:00.000 2009-07-31 00:00:00.000
2009-06-01 00:00:00.000 2009-06-30 00:00:00.000
2009-05-01 00:00:00.000 2009-05-31 00:00:00.000


SELECT *
FROM TABLE_A A
RIGHT JOIN TABLE_B B ON A.COL_C = B.StartDate

sfds    jkjlj   2009-07-01 00:00:00.000 2009-07-01 00:00:00.000 2009-07-31 00:00:00.000
NULL    NULL    NULL    2009-06-01 00:00:00.000 2009-06-30 00:00:00.000
NULL    NULL    NULL    2009-05-01 00:00:00.000 2009-05-31 00:00:00.000
0 голосов
/ 17 мая 2011

Что я обычно делаю при присоединении к датам, так это сначала преобразовываю их в целые числа, поскольку объединение по датам (1) часто дает неожиданные результаты, а (2) это медленно.

Я бы сделал объединение так:

Select * 
From
TABLE_A A 
Right Join 
TABLE_B B 
On 
((Year(A.COL_C)*10000) + (Month(A.COL_C)*100) + Day(A.COL_C)) = ((Year(B.StartDate)*10000) + (Month(B.StartDate)*100) + Day(B.StartDate))

Однако кажется, что вы действительно хотите присоединиться к году и месяцу, поскольку дата в Таблице_A всегда 1-ая. Я бы сделал это так:

Select * 
From
TABLE_A A 
Right Join 
TABLE_B B 
On 
((Year(A.COL_C)*100) + Month(A.COL_C)) = ((Year(B.StartDate)*100) + Month(B.StartDate))

Надеюсь, это поможет.

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