Функция Oracle sql count ()?

#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 определяется в скобках so ag.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
  

Всем спасибо за помощь.