#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. Спасибо за ваш ответ, я ценю время, которое вы потратили, отвечая на мой вопрос. Хороший фрагмент кода, но, к сожалению, это не совсем то, что я искал. Я нашел решение в одном из предыдущих ответов, которое является лишь небольшой поправкой к тому, что я делал. Еще раз спасибо.