Проверка статуса элемента в master-detail в MSSQL

#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: «сложный» в глазах наблюдателя 😉 Я нахожу подзапросы простыми на глаз. Я согласен, существует более одного способа скинуть кошку … но вам понадобятся три внутренних соединения, чтобы они были семантически одинаковыми, как мне кажется.