У меня есть временная таблица, из которой я создаю запрос в следующем формате. Он содержит запись для каждого идентификатора клиента, года и месяца за несколько лет.
Заказчик | CustomerID | Год | Месяц
бывший.
Foo | 12345 | 2008 | 12
Foo | 12345 | 2008 | 11
Bar | 11224 | 2007 | 7
Когда я присоединяю эту временную таблицу к другой таблице следующего формата, я получаю гораздо больше результатов, чем ожидал.
EventID | CustomerID | Дата открытия
бывший.
1100 | 12345 | '2008-12-11 10:15:43'
1100 | 12345 | '2008-12-11 11:25:17'
Я пытаюсь получить набор результатов с количеством событий вместе с клиентом, годом и месяцем, как это.
SELECT COUNT(EventID), Customer, Year, Month
FROM [Event]
JOIN #T ON [Event].CustomerID = #T.CustomerID
WHERE [Event].DateOpened BETWEEN '2008-12-01' AND '2008-12-31'
GROUP BY Customer, Year, Month
ORDER BY Year, Month
Я получаю рекорд за каждый год и месяц, а не только за декабрь 2008 года.


Проблема в том, что в #T есть две строки с CustomerID = 12345. Каждая из этих строк соединяется с каждой строкой в Event. Если вам нужен только CustomerID в декабре, вам также нужно отфильтровать #T:
SELECT COUNT(EventID), Customer, Year, Month
FROM [Event]
JOIN #T ON [Event].CustomerID = #T.CustomerID
WHERE [Event].DateOpened BETWEEN '2008-12-01' AND '2008-12-31'
AND #T.Year = 2008
AND #T.Month = 12
GROUP BY Customer, Year, Month
ORDER BY Year, Month
Если у вас есть другие ожидания, вам лучше прояснить свой вопрос.
Вы указываете дату в таблице событий, но не в соединении, поэтому она объединяет все записи из временной таблицы с соответствующим идентификатором клиента.
Попробуй это:
SELECT COUNT(e.EventID), T.Customer, T.Year, T.Month
FROM [Event] e
INNER JOIN #T T ON (
T.CustomerID = e.CustomerID and
T.Year = year(e.DateOpened) and
T.Month = month(e.DateOpened)
)
WHERE T.Year = 2008
and T.Month = 12
GROUP BY T.Customer, T.Year, T.Month
ORDER BY T.Year, T.Month
Возможно, вы имеете в виду:
SELECT COUNT(EventID)
,Customer
,Year
,Month
FROM [Event]
INNER JOIN #T
ON [Event].CustomerID = #T.CustomerID
AND YEAR([Event].DateOpened) = #T.YEAR
AND MONTH([Event].DateOpened) = #T.MONTH
WHERE [Event].DateOpened >= '2008-12-01'
AND [Event].DateOpened < '2009-01-01'
GROUP BY Customer
,Year
,Month
ORDER BY Year
,Month
Обратите внимание, я исправил еще одну скрытую ошибку в вашем коде: ваш BETWEEN будет исключать даты, такие как '2008-12-31 10:15:43'. Вы можете использовать этот или аналогичный метод.
Кроме того, мне нравится, как вы выполняете соединение между Event.DateOpened и # T.Year и # T.Month. Более аккуратный, чем мой ответ.
Есть много способов снять шкуру с этой кошки - и много способов обрезать код ПУТЬ ВНИЗ, если дизайн БД чище. Я ненавижу смешивать столбцы YEAR и MONTH int и столбцы datetime - выберите одно соглашение и придерживайтесь его.
Похоже, что #T имеет избыточную информацию, если вам нужно только имя клиента.
Вы можете решить это с помощью подзапроса
SELECT COUNT(EventID), (select TOP 1 #T.Customer from #T Where #T.CustomerID = [Event].CustomerID ), Year, Month
FROM [Event]
WHERE [Event].DateOpened BETWEEN '2008-12-01' AND '2008-12-31'
GROUP BY CustomerID, Year, Month
ORDER BY Year, Month
Хороший улов на усечении диапазона. Если DateOpened был преобразован в значение DATE (без компонента времени), оригинал будет в порядке.