Я считаю, что проблема в том, что PRODUCTATTRIBUTES
является таблицей значений атрибутов сущности (EAV), с которой, как известно, трудно справляться в запросах.
Обратите внимание, что при втором выполнении запроса, который включает параметры, значение, введенное для @IN_set
, отображается в столбце KeySet
, поскольку вы не различаете значения PRODUCTATTRIBUTE
(CodeSet
против KeySet
) в вашем предложении WHERE
.
Чтобы упростить логику c в подобных запросах, я обычно несколько раз присоединяюсь к таблице EAV, создавая подзапросы, которые содержат только пары ключ / значение, которые мне нужны для каждого атрибута. Итак, в этом случае я бы присоединился к PRODUCTATTRIBUTES
дважды, один раз, чтобы получить интересующие значения CodeSet
, затем снова, чтобы получить значения KeySet
. Я также перенесу агрегацию на эти подзапросы, что устраняет неоднозначность, а также уменьшает объем данных, загружаемых в память.
Это не проверялось, конечно, из-за отсутствия таблиц и данных для сравнения, но обоснованное предположение о новой структуре выглядело бы примерно так:
SELECT IDLOCK, DT, LOCKTYPE,
CS.CodeSet,
KS.KeySet
FROM LOCKREGISTER LR LEFT JOIN
LOCKTYPES T
ON LR.IDLOCKTYPE = T.IDLOCKTYPE LEFT JOIN
( -- Sub-query to get 'CodeSet' values by IDPRODUCT
SELECT
IDPRODUCT,
MAX(VALUE) AS CodeSet
FROM PRODUCTATTRIBUTES
WHERE PRODUCTATTRIBUTE = 'CodeSet'
GROUP BY IDPRODUCT
) AS CS
ON LR.IDPRODUCT = CS.IDPRODUCT LEFT JOIN
( -- Sub-query to get 'KeySet' values by IDPRODUCT
SELECT
IDPRODUCT,
MAX(VALUE) AS KeySet
FROM PRODUCTATTRIBUTES
WHERE PRODUCTATTRIBUTE = 'KeySet'
GROUP BY IDPRODUCT
) AS KS
ON LR.IDPRODUCT = KS.IDPRODUCT
WHERE LR.DT BETWEEN IIF(@IN_DTMIN IS NULL,GETDATE(),@IN_DTMIN) AND IIF(@IN_DTMAX IS NULL,GETDATE(),@IN_DTMAX)
AND (KS.KeySet like ISNULL(@IN_key,'%') OR (KS.KeySet IS NULL AND @IN_key IS NULL))
AND (CS.CodeSet like ISNULL(@IN_set,'%') OR (CS.CodeSet IS NULL AND @IN_set IS NULL))
AND (T.LOCKTYPE like ISNULL(@IN_locktype,'%') OR (T.LOCKTYPE IS NULL AND @IN_locktype IS NULL));