SQL: запрос для проверки соответствия столбца определенным критериям, выполняет ли он одно действие, если не выполняет другое

#sql #sqlcommand #join

#sql #sqlcommand #Присоединиться

Вопрос:

Мне было довольно сложно сформулировать, что я хочу сделать в названии, поэтому я постараюсь сделать все возможное, чтобы объяснить сейчас!

У меня есть две таблицы, которые я использую:

 Master_Tab and Parts_Tab
  

Parts_Tab содержит следующую информацию:

 Order_Number | Completed| Part_Number|

   |    1       |     Y    |     64     |
   |    2       |     N    |     32     |
   |    3       |     Y    |     42     |
   |    1       |     N    |     32     |
   |    1       |     N    |     5      |
  

Master_Tab содержит следующую информацию:

 Order_Number|
 1           |  
 2           |
 3           |
 4           |
 5           |
  

Я хочу сгенерировать запрос, который вернет ВСЕ порядковые номера, перечисленные в Master_Tab, при следующих условиях…

Для каждого Order_Number я хочу проверить таблицу Parts_Tab, чтобы увидеть, есть ли какие-либо части, которые не завершены (завершено = ‘N’). Затем для каждого Order_Number я хочу подсчитать количество незавершенных частей, которые имеет против него заказ. Если Order_Number не содержит незавершенных частей или его нет в Parts_Table, я хочу, чтобы значение count было равно 0.

Таким образом, таблица, которая будет сгенерирована, будет выглядеть следующим образом:

 Order_Number | Count_of_Non_Complete_Parts|
1            |            2               |
2            |            1               |
3            |            0               |
4            |            0               |
5            |            0               |
  

Я надеялся, что использование другого типа соединения в таблицах сделает это, но я явно упускаю трюк!

Любая помощь очень ценится!

Спасибо.

Ответ №1:

Я использовал COALESCE для преобразования NULL в ноль, где это необходимо. В зависимости от платформы вашей базы данных вам может потребоваться использовать другой метод, например ISNULL , или CASE .

 select mt.Order_Number, 
    coalesce(ptc.Count, 0) as Count_of_Non_Complete_Parts
from Master_Tab mt
left outer join (
    select Order_Number, count(*) as Count
    from Parts_Tab 
    where Completed = 'N'
    group by Order_Number
) ptc on mt.Order_Number = ptc.Order_Number
order by mt.Order_Number
  

Комментарии:

1. COALESCE не должно быть необходимости для OUTER JOIN . Счетчик будет равен нулю, а не НУЛЮ. По крайней мере, в Postgresql.

2. @Andrew, COALESCE охватывает случай, когда в подзапросе нет соответствующей строки, и, следовательно NULL , возвращается.

3. Вы правы. Я недостаточно подумал о случае подзапроса. Сам Count вернет ноль, а не NULL, но когда вы присоединитесь к подзапросу, у вас будет просто NULL . С другой стороны, нет необходимости в подзапросе для OP. Ей просто нужно LEFT JOIN .

4. Привет, спасибо за твой ответ RedFilter… Я думаю, что это тоже работает, я дважды проверю данные и дам вам знать! Большое спасибо.

Ответ №2:

Вы ищете LEFT JOIN .

 SELECT mt.order_number, count(part_number) AS count_noncomplete_parts
FROM master_tab mt LEFT JOIN parts_tab pt
ON mt.order_number=pt.order_number AND pt.completed='N'
GROUP BY mt.order_number;
  

Также можно вставить pt.completed='N' в предложение WHERE , но вы должны быть осторожны с NULL . Вместо AND вы можете иметь

 WHERE pt.completed='N' OR pr.completed IS NULL
  

Комментарии:

1. Lazurus Привет, спасибо за ваш быстрый ответ. Изначально я выполнял именно этот запрос, но он возвращает только заказы, в которых есть части, которые в нем не завершены. Я хочу вернуть все заказы. Если в заказе есть только завершенные части (завершено = ‘Y’), то количество частей должно быть равно 0. Также, если в заказе вообще нет записей в parts_tab, тогда количество частей должно быть равно 0.

2. @Tamara, Ммм, я попробовал это в Postgresql и получил нули. Если вы используете a LEFT JOIN , вы должны получить (по крайней мере) одну строку для каждой строки в master_tab . Вы уверены, что у вас не было INNER JOIN ?

3. @LAzarus, да, я просто скопировал ваш код и изменил его на имена таблиц и полей, просто чтобы проверить, что я не сделал это неправильно раньше. Он вернул точно то же самое… Я думал, что левое соединение решит это, но это не так ?! Confused.com

4. Какая БД. Попробуйте SELECT mt.order_number as m, pt.order_number as p FROM [left join] и посмотрите, сколько строк вы получите. Убедитесь, что у вас нет предложения WHERE . Это позволяет внешнему соединению сокращать строки.

5. Эй, я думаю, что это работает! Я дважды проверю правильность данных в моей системе и дам вам знать :). Спасибо, пока 🙂

Ответ №3:

 SELECT mt.Order_Number SUM(tbl.Incomplete) Count_of_Non_Complete_Parts
FROM Master_Tab mt
    LEFT JOIN (
       SELECT Order_Number, CASE WHEN Completed = 'N' THEN 1 ELSE 0 END Incomplete
       FROM Parts_Tab
     ) tbl on mt.Order_Number = tbl.Order_Number
GROUP BY mt.Order_Number
  

Добавьте WHERE предложение во внешний запрос, если вам нужно отфильтровать определенные порядковые номера.

Комментарии:

1. Вы все еще хотите JOIN , я думаю, показывать заказы из Master без записей в Parts

2. @JNK, я полностью пропустил это требование в вопросе … ответ обновлен.

Ответ №4:

Я думаю, что проще всего вставить туда подзапрос. Я думаю, это должно быть самоочевидным, если не стесняйтесь задавать какие-либо вопросы.

 CREATE TABLE #Parts
(
    Order_Number int,
    Completed char(1),
    Part_Number int
)

CREATE TABLE #Master
(
    Order_Number int
)

INSERT INTO #Parts
SELECT 1, 'Y', 64 UNION ALL
SELECT 2, 'N', 32 UNION ALL
SELECT 3, 'Y', 42 UNION ALL
SELECT 1, 'N', 32 UNION ALL
SELECT 1, 'N', 5 

INSERT INTO #Master
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6

SELECT M.Order_Number, ISNULL(Totals.NonCompletedCount, 0) FROM #Master M
    LEFT JOIN (SELECT P.Order_Number, COUNT(*) AS NonCompletedCount FROM #Parts P
                WHERE P.Completed = 'N'
                GROUP BY P.Order_Number) Totals ON Totals.Order_Number = M.Order_Number
  

Комментарии:

1. Спасибо за ваш ответ, я ценю время, которое вы потратили, отвечая на мой вопрос. Хороший фрагмент кода, но, к сожалению, это не совсем то, что я искал. Я нашел решение в одном из предыдущих ответов, которое является лишь небольшой поправкой к тому, что я делал. Еще раз спасибо.