#sql #oracle #count #conditional-statements
#sql #Oracle #подсчет #условные операторы
Вопрос:
У меня проблема с функцией count(). Я хочу, чтобы она учитывалась только при определенных условиях.
Что я хочу сделать, так это отобразить для каждой компании название компании, имя руководителя компании и количество арендных платежей, превышающих три дня, сделанных в 2010 году.
Итак, условие таково: количество арендных платежей, превышающих три дня, сделанных в 2010 году.
Поэтому, если у компании нет аренды, удовлетворяющей условию, ее не следует исключать из результирующей таблицы, а вместо этого следует записать ноль. Например:
company 1 -------------------- BOSS 1-----------------------2
company 2---------------------- BOSS 2---------------------- 0 --doesn't satisfy the condition: 0 rentals
company 3-----------------------BOSS 3 ----------------------5
company 4---------------------- BOSS 4--------------------------1
company 4 ----------------------BOSS 5 ----------------------- 0 --doesn't satisfy the condition: 0 rentals
AND NOT
company 1----------------------BOSS 1---------------------------2
company 3--------------------- BOSS 3---------------------------5
company 4----------------------BOSS 4 --------------------------1
В моих sql-кодах отображается вторая таблица, а не первая таблица. Это мой код:
SELECT ag.nom_agence as NOM_AGENCE, ag.responsable_agence, count(*) as RESPONSABLE
FROM agences ag, locations l
WHERE ag.id_agence = l.id_agence AND
l.date_location BETWEEN to_date('01/01/2010','DD.MM.YYYY') AND to_date('31/12/2010','DD.MM.YYYY') AND
l.duree > 3
group by ag.nom_agence,ag.responsable_agence
Я хочу что-то в этом формате (без предложения where):
count(l.date_location BETWEEN to_date('01/01/2010','DD.MM.YYYY') AND to_date('31/12/2010','DD.MM.YYYY') AND
l.duree > 3)
Есть идеи? Спасибо.
Ответ №1:
Вам нужно использовать внешнее соединение с таблицей местоположений, чтобы убедиться, что вы всегда извлекаете все арендные платы за период, независимо от их продолжительности.
Затем подсчитайте количество арендных платежей> 3 дней.
Попробуйте это:
SELECT
NOM_AGENCE,
RESP_AGENCE,
SUM(RESPONSABLE)
FROM
(
SELECT
ag.nom_agence as NOM_AGENCE,
ag.responsable_agence RESP_AGENCE,
CASE
WHEN l.duree > 3 THEN 1
ELSE 0
END RESPONSABLE
FROM
agences ag LEFT OUTER JOIN locations l ON ag.id_agence = l.id_agence
AND l.date_location
BETWEEN to_date('01/01/2010','DD.MM.YYYY')
AND to_date('31/12/2010','DD.MM.YYYY')
)
GROUP BY
NOM_AGENCE,
RESP_AGENCE
Комментарии:
1.
l.duree > 3
не фильтрует его. На самом деле мне это нужно, чтобы удовлетворить условиюthe number of rentals exceeding three days
. НоWHERE
предложение ограничивает результаты2. попробуйте мое последнее редактирование, должно сработать сейчас — я был немного смущен исходным запросом
3. На самом деле это не сработало
(error:missing keyword)
, но дало мне представление о том, как использоватьcase
.4. извините, ошибка вырезания и вставки, я оставил значение count (*), после
else 0
которого его не должно было быть .. работает ли это сейчас?5. Существует проблема с предложением group by .
agences ag
определяется в скобках soag.nom_agence
иag.nom_responsble
не определено
Ответ №2:
Попробуйте следующее (я не пробовал).
Это в основном и внешнее соединение между таблицей агентств и арендными платами, сгруппированными по агентствам после вашего фильтра поиска.
NVL преобразует количество для агентств, у которых нет совпадения в правильном запросе, в 0.
select left.id_agence, left.nom_agence, left.responsable_agence, NVL(right.count, 0)
from
(select id_agence, nom_agence, responsable_agence from agences) left
left outer join
(
SELECT id_agence, count(*) as count
FROM locations
WHERE date_location BETWEEN to_date('01/01/2010','DD.MM.YYYY') AND to_date('31/12/2010','DD.MM.YYYY') AND
duree > 3
group by id_agence
) right
on left.id_agence = right.id_agence
Комментарии:
1. Это работает, но я не понимаю этого
NVL
предложения. Кажется, для меня это продвинуто, лол. Я только начал изучать Oracle sql. Хотя спасибо 🙂2. @mkab, NVL просто заменяет значение другим, если значение равно null. Например, NVL(3, 4) вернет 3, поскольку 3 не равно нулю, но NVL(NULL, 12) вернет 12. Поскольку внешние соединения приводят к нулевым значениям, когда значения наборов данных не совпадают, NVL позволяет нам рассматривать их как 0.
Ответ №3:
Используйте предложение having:
having count(*) > 0
Ответ №4:
Мой быстрый ответ заключается в том, что вам нужно выполнить ЛЕВОЕ СОЕДИНЕНИЕ, а не ВНУТРЕННЕЕ СОЕДИНЕНИЕ, которое вы делаете. Попробуйте это:
SELECT ag.nom_agence as NOM_AGENCE, ag.responsable_agence, count(*) as RESPONSABLE
FROM agences ag
left join locations l on l.id_agence = ag.id_agence
WHERE
l.date_location BETWEEN to_date('01/01/2010','DD.MM.YYYY') AND
to_date('31/12/2010','DD.MM.YYYY') AND
l.duree > 3
group by ag.nom_agence,ag.responsable_agence
Комментарии:
1. Та же проблема.
WHERE
Предложение ограничивает результаты. Это дает мне ту же таблицу, что иthe inner join
Ответ №5:
SELECT ag.nom_agence as NOM_AGENCE, ag.responsable_agence, count(*) as RESPONSABLE
FROM agences ag LEFT OUTER JOIN locations l ON ag.id_agence = l.id_agence
WHERE l.date_location BETWEEN to_date('01/01/2010','DD.MM.YYYY') AND to_date('31/12/2010','DD.MM.YYYY') AND l.duree > 3
group by ag.nom_agence,ag.responsable_agence
Ключ в том, что вам нужно выполнить ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ, которое извлечет все записи из вашей таблицы агентств независимо от того, есть ли какие-либо совпадающие записи в местоположениях
Комментарии:
1. Та же проблема.
WHERE
Предложение ограничивает результаты. Это дает мне ту же таблицу, что иthe inner join
Ответ №6:
Я нашел запрос. Это дает мне правильную таблицу
SELECT ag.nom_agence as NOM_AGENCE, ag.responsable_agence as RESPONSABLE, count(case when to_char(l.date_location, 'YYYY') = '2010' and l.duree>3 then 1 end) as NOMBRE
FROM agences ag, locations l
WHERE ag.id_agence = l.id_agence
group by nom_agence, responsable_agence
Всем спасибо за помощь.