#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
У меня есть три таблицы, а именно:
- Продукт
- Вариант продукта
- Параметр размера
Product
является главной таблицей, productvariant
является ее дочерней таблицей it и sizevariant
является дочерней таблицей productvariant.
Все эти таблицы имеют столбец статуса, который указывает, являются ли они активными или нет. Я хочу проверить, есть ли какие-либо продукты, у которых productvariants
и sizevariants status
отключен, но product
сам по себе жив.
Комментарии:
1. вам действительно нужно проверять параметры размера для продукта? похоже, вы хотели бы проверить productvariant для product, а затем проверить sizevariant для productvariant
Ответ №1:
select *
from product p
where p.status = 'alive'
and not exists (select 1
from productvariant
where productid = p.id
and status='alive')
должен предоставить вам все продукты, у которых нет «живого» варианта. следуя той же формуле, вы также можете проверить наличие вариантов продукта без каких-либо вариантов «живого» размера:
select *
from productvariant pv
where p.status = 'alive'
not exists (select 1
from sizevariant
where productvariantid = pv.id
and status='alive')
Комментарии:
1. запрос показывает мне все продукты, которые мертвы, но мне нужны только те, чьи дочерние элементы мертвы, а они сами нет. Я пытаюсь создать курсор для выполнения этой задачи.
2. @kaibuki, я обновил, чтобы ограничить возвращаемый набор только теми, в которых продукт является «живым». я не понимаю, почему вы использовали курсор для этой задачи.
3. @kaibuki:
status <> 'alive'
Это то же самое, чтоstatus ='dead'
?4. Рассмотрим «живой» продукт, у которого нет вариантов: ваш первый запрос выберет его, но действительно ли можно сказать, что он находится в наборе «продукты, статус productvariants и sizevariants которых недоступен»?
5. эти семантические игры утомительны. если мой пост кому-нибудь поможет, отлично.
Ответ №2:
есть ли какие-либо продукты, статус
productvariants
иsizevariants
которых мертв, но сам продукт жив
SELECT P1.product_ID
FROM Products AS P1
INTERSECT
SELECT V1.product_ID
FROM productvariants AS V1
WHERE V1.status = 'Dead'
INTERSECT
SELECT V1.product_ID
FROM productvariants AS V1
INNER JOIN sizevariants AS S1
ON V1.product_variant_ID = S1.product_variant_ID
WHERE S1.status = 'Dead';
Альтернативно (предупреждение: может выглядеть излишне сложным):
SELECT P1.product_ID
FROM Products AS P1
WHERE P1.status = 'Alive'
AND EXISTS (
SELECT *
FROM productvariants AS V1
WHERE P1.product_ID = V1.product_ID
AND V1.status = 'Dead'
)
AND EXISTS (
SELECT *
FROM sizevariants AS S1
INNER JOIN productvariants AS V1
ON V1.product_variant_ID = S1.product_variant_ID
WHERE P1.product_ID = V1.product_ID
AND S1.status = 'Dead'
);
Комментарии:
1. у вас возникли некоторые проблемы с псевдонимами в ваших подзапросах, и, я повторю, я не задавал этот вопрос, оригинальным постером был @kaibuki. вы, кажется, довольно агрессивно относитесь к этому, хотя …
![]()
2. кроме того, первый вариант кажется излишне сложным. вы должны быть в состоянии выполнить это с помощью 2 внутренних соединений и без коррелированных подзапросов
3. @nathan gonzalez: «сложный» в глазах наблюдателя
Я нахожу подзапросы простыми на глаз. Я согласен, существует более одного способа скинуть кошку … но вам понадобятся три внутренних соединения, чтобы они были семантически одинаковыми, как мне кажется.