Помощь в программировании SQL с использованием count и max ..etc

У меня есть серия таблиц:

  • TECH PERSONNEL (pplSoft, fname, lname, pittID, expertise, office phone) где fname — имя, а lname — фамилия.

  • USERS (pplSoft, fname, lname, pittID, office phone)

  • CATEGORIES (category id, category, description), где в этой таблице перечислены все возможные категории отправленных заявок.

  • INVENTORY(machine name, IP, network port, MACADDR, location id)

  • LOCATIONS(location id, location, building, notes)

  • TICKETS (ticket number, owner pplSoft, date submitted, date closed, days worked on, category id, machine name, location, description)

  • ASSIGNMENT (ticket number, tech pplSoft, date assigned, status), где статус удержания является перечислением, может быть: назначено, в процессе, делегировано, закрыто успешно или закрыто неудачно.

Моя задача — перечислить в Device Name все названия машин, на которых было максимальное количество проблем за два месяца — декабрь 2011 и январь 2012.

Я должен превратить это в SQL.

Могу ли я сделать что-то подобное?

select machine_name 
from tickets 
where date_submitted >= '01-DEC-2012' and 'date_submitted <= '31-JAN-2012'  

Но мне нужно считать билеты или использовать макс?

Как мне добиться прогресса отсюда?


person CDev33    schedule 12.02.2012    source источник
comment
Можете ли вы привести пример ввода и вывода, чтобы пояснить, что вы хотите сделать?   -  person Albin Sunnanbo    schedule 13.02.2012
comment
я хочу найти и перечислить все названия устройств (машин), у которых было максимальное количество проблем в течение декабря и января   -  person CDev33    schedule 13.02.2012
comment
Поскольку ни один из столбцов ни в одной из таблиц не является «именем устройства», вопрос, как указано, остается без ответа. Элегантную вариацию лучше оставить на занятиях по английскому языку; в вычислениях жесткое обращение к объекту одним именем помогает всем, включая вас. Предположительно, проблема заключается в следующем: С какими именами машин было больше всего проблем в декабре 2011 г. и январе 2012 г., исходя из подсчета количества билетов, открытых для машины? Это примерно так?   -  person Jonathan Leffler    schedule 13.02.2012


Ответы (4)


Как и в случае любого сложного SQL-запроса, секрет заключается в том, чтобы разбить его на части, желательно независимо тестируемые части.

Первая проблема состоит в том, чтобы установить подсчет количества билетов, выданных каждой машине за рассматриваемый период. Какой здесь критерий? Вероятно, если у машины возникла проблема, которая началась в ноябре 2011 г. и распространилась на декабрь 2011 г., ее следует учитывать; аналогично, если проблема была начата в январе 2012 г., но завершена в феврале 2012 г., это должно быть засчитано. Итак, нам нужно:

SELECT machine_name, COUNT(*) AS num_tickets
  FROM tickets
 WHERE date_completed >= '01-Dec-2011' AND date_submitted <= '31-Jan-2012'
 GROUP BY machine_name;

Если вы решите, что учитываются только даты подачи заявок, измените критерий, чтобы дважды ссылаться на date_submitted; аналогичным образом, если учитываются только даты, когда билеты были заполнены, дважды укажите date_completed. Обратите внимание, что если у машины есть тикет, который был запущен в ноябре и не разрешен до февраля, приведенный выше запрос засчитает его; если вы используете любую из альтернатив, у этой машины не было проблем в течение рассматриваемого периода.

Это говорит нам о том, сколько билетов было открыто для автомата в течение определенного периода времени. Теперь нам нужно найти, какое количество билетов максимальное:

SELECT MAX(num_tickets) AS max_tickets
  FROM (SELECT machine_name, COUNT(*) AS num_tickets
          FROM tickets
         WHERE date_completed >= '01-Dec-2011' AND date_submitted <= '31-Jan-2012'
         GROUP BY machine_name
       );

Теперь нам нужно выбрать имя(а) машины, на которой было такое количество билетов:

SELECT machine_name
  FROM (SELECT MAX(num_tickets) AS max_tickets
          FROM (SELECT machine_name, COUNT(*) AS num_tickets
                  FROM tickets
                 WHERE date_completed >= '01-Dec-2011' AND date_submitted <= '31-Jan-2012'
                 GROUP BY machine_name
               )
        ) AS n
  JOIN (SELECT machine_name, COUNT(*) AS num_tickets
          FROM tickets
         WHERE date_completed >= '01-Dec-2011' AND date_submitted <= '31-Jan-2012'
         GROUP BY machine_name
       ) AS m
    ON n.max_tickets = m.num_tickets;

Предполагая, что Oracle поддерживает предложение WITH, это можно упростить (значительно):

WITH t AS
    (SELECT machine_name, COUNT(*) AS num_tickets
       FROM tickets
      WHERE date_completed >= '01-Dec-2011' AND date_submitted <= '31-Jan-2012'
      GROUP BY machine_name
    )
SELECT t.machine_name
  FROM t
  JOIN (SELECT MAX(num_tickets) AS max_tickets FROM t) AS m
    ON t.num_tickets = m.max_tickets;

Предупреждение: я использовал "псевдоним AS" в подзапросах, как это поддерживается стандартом SQL. Я считаю, что Oracle не разрешает «псевдоним AS» и требует только «псевдоним» после имен таблиц; Я не уверен, относится ли это также к именам для подзапросов. Если нотации «AS m» и «AS n» вызывают проблемы, попробуйте удалить AS. Вы можете найти аналогичную проблему с переименованием столбцов «AS num_tickets» и т. д., но я считаю, что Oracle разрешает AS в этом контексте.

Предположительно, это всего лишь один из серии вопросов, поскольку для ответа, похоже, не требуется ни одна из таблиц, кроме таблицы «Билеты». Предположительно, другие вопросы требуют использования других таблиц.

person Jonathan Leffler    schedule 12.02.2012

Вам нужно использовать group by.

select machine_name, count(*) as numMachines
from tickets
where date_submitted >= '01-DEC-2011' and 'date_submitted <= '31-JAN-2012'
group by machine_name
order by numMachines desc
person Albin Sunnanbo    schedule 12.02.2012
comment
Большое вам спасибо... но примет ли это максимальное количество проблем? (где, я думаю, вы подсчитываете количество билетов, отправленных на машину, правильно? и перечисляете каждую машину, на которой их больше всего?) - person CDev33; 13.02.2012

Ваш запрос вернет вам одну строку для каждой проблемы. Ваш первый шаг — сгруппировать результат по машинам, чтобы получить по одной строке для каждой машины. Затем вы можете добавить столбец подсчета, который показывает, сколько проблем было для этой машины.

Чтобы найти максимальное количество проблем, вам нужно поместить свой запрос в подзапрос, чтобы вы могли извлечь максимум. Затем вы можете использовать это в качестве подвыборки в предложении have, чтобы вернуть машины с этим максимальным количеством.

SELECT machine_name, COUNT(machine_name) AS ticket_count
  FROM tickets
  WHERE date_submitted >= '01-DEC-2012' AND date_submitted <= '31-JAN-2012'
  GROUP BY machine_name
  HAVING ticket_count = (
    SELECT MAX(ticket_count) FROM (
      SELECT COUNT(machine_name) AS ticket_count
        FROM tickets
        WHERE date_submitted >= '01-DEC-2012' AND date_submitted <= '31-JAN-2012'
        GROUP BY machine_name
    )
  )
person Neil    schedule 12.02.2012

person    schedule
comment
вам понадобится группа по предложению @Maarten - person Naval; 13.02.2012
comment
@Naval: я был слишком быстр. Спасибо, что указали мне на эти ошибки. - person Maarten Kesselaers; 13.02.2012