В вашем запросе происходит очень много вещей, которые могут вызывать проблемы.Есть также некоторые области неопределенности, которые, вероятно, следует устранить.Для начала попробуйте этот запрос:
SELECT
DateAdd(Day, DateDiff(Day, 0, X.ScanTime), 0) ScanDate,
X.ModelNumber,
Coalesce(Z.Total, 0) Total,
Coalesce(Z.Sold, 0) Sold
FROM
maxis.dbo.maxis_IMEI_Model X
LEFT JOIN (
SELECT
Z.ModelNumber,
DateAdd(Day, DateDiff(Day, 0, Z.ScanTime), 0) ScanDate,
Count(DISTINCT M.IDNO) Total,
Count(Y.IDNO) Sold
FROM
micro_model Z
LEFT JOIN micro_model_sold Y
ON Z.IDNO = Y.IDNO
GROUP BY
DateDiff(Day, 0, Z.ScanTime),
Z.ModelNumber
) Z
ON X.ModelNumber = Z.ModelNumber
AND X.ScanTime >= Z.ScanDate
AND X.ScanTime < Z.ScanDate + 1
WHERE
X.ScanTime >= '20110101'
AND X.ScanTime < '20110126'
Преобразование в символ для сравнения целых дат (путем отсечки символов, представляющих время) очень неэффективно.Лучшая практика - это делать, как я показал в предложении WHERE.Обратите внимание, что я увеличил окончательную дату на один день, а затем сделал эту точку исключительной , используя меньше чем вместо меньше или равно (что и делает BETWEEN).Все соединения также необходимо изменить.Наконец, когда необходимо , чтобы удалить временную часть даты, метод DateDiff, который я здесь показываю, является лучшим (есть немного более быстрый метод, который гораздо сложнее понять, поэтому я не могу его рекомендовать,но если вы используете SQL Server 2008, вы можете просто набрать Convert(date, DateColumn)
, что является самым быстрым из всех).
Использование формата даты «01/01/2011» не является региономбезопасный.Если ваш запрос когда-либо использовался на компьютере, на котором язык был изменен на язык с форматом даты по умолчанию DMY, ваши даты будут интерпретироваться неправильно, меняя месяц и день и вызывая ошибки.Для обеспечения безопасности используйте формат yyyymmdd
.
Использование коррелированных подзапросов (ваши операторы SELECT в скобках для извлечения значений столбцов из других таблиц) неудобно и в некоторых случаях приводит к очень плохому выполнениюпланы.Несмотря на то, что оптимизатор часто может преобразовать их в правильные объединения, нет никакой гарантии.Другим людям, смотрящим на запрос, также становится очень трудно понять, что он делает.Лучше выразить такие вещи, используя внешние соединения, как показано.Я преобразовал коррелированные подзапросы в производные таблицы.
Использование DISTINCT
вызывает беспокойство.Ваш запрос не должен возвращать несколько строк для каждой модели.Если это так, то с запросом логически что-то не так, и вы, вероятно, получаете неверные данные.
I думаю Я объединил два коррелированных подзапроса в своем производномтаблицы правильно.Но у меня нет примеров данных и всей информации о схеме, так что это мое лучшее предположение.В любом случае, мой запрос должен дать вам идеи.
Я полностью переформатировал ваш запрос, потому что было почти невозможно увидеть, что он делает.Я рекомендую вам сделать немного больше форматирования в вашем собственном коде.Это поможет вам и всем, кто придет за вами, быстрее понять, что происходит.Если вы зададите больше вопросов по SQL на этом сайте, вам нужно лучше отформатировать собственный код.Пожалуйста, сделайте это, а также используйте кнопку «блок кода» или просто сделайте отступ всех строк кода на 4 пробела вручную, чтобы он был отформатирован веб-страницей как блок кода.
Youзнаете, глядя на мой запрос немного больше, становится ясно, что я не понимаю отношения между maxis_IMEI_Model
и другими таблицами.Пожалуйста, объясните немного больше, что означают таблицы и какой результат вы хотите увидеть.
Возможно, проблемы в моем запросе могут быть решены с помощью простого GROUP BY
и бросая несколько SUM
s в числовые столбцы., но я не уверен на 100%.Может случиться так, что таблица maxis_IMEI_Model
должна полностью исчезнуть или перейти в свою собственную производную таблицу, где она сгруппирована отдельно, прежде чем присоединиться.