Проблема с предложением SQL WHERE IF

#mysql

#mysql

Вопрос:

У меня проблема с кодом SQL / Java. Основное наложение заключается в следующем: база данных MySQL с таблицей. В этой таблице есть несколько столбцов. Один столбец состоит из имен. Связанный столбец — месяцы. В третьем столбце есть количество. Таким образом, пример таблицы будет

 john - january - 5
john - january - 6 
mary - january - 5
Alex - February- 5
John - February - 6
John - February - 4
Mary - February - 3
John - march - 4
  

Таблица продолжается до мая месяца.

Итак, Джон появляется через пять месяцев, Мэри — через 3, а Алекс — через один. В настоящее время мой SQL-запрос выглядит примерно так.

     select name, sum(count)/4 
    from table where (category ='something' 
    AND month not like 'May') group by name;
  

В принципе, предполагается, что этот запрос просто отображает каждое имя со средним количеством в месяц. Следовательно, сумма будет разделена на четыре (поскольку я исключаю май, поэтому она должна делиться на январь-апрель / 4). Однако проблема в том, что некоторые имена появляются только через один месяц (или два или три).

Это означает, что для этого имени сумма подсчетов будет разделена только на это конкретное число, чтобы получить среднее количество за месяцы. Как бы я поступил по этому поводу? Я чувствую, что для этого потребуется некоторый оператор if в предложении where. Вроде как, где, если количество различных (поскольку месяцы могут повторяться) равно определенному числу, затем разделите сумму (количество) на это число для каждого имени?

Кроме того, я думаю, что это может быть не проблема с предложением where if. Я прочитал несколько форумов, где, возможно, можно было бы использовать какое-либо использование case?

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

1. это mysql или sql-server?

2. «база данных mysql», я считаю, что она просто помечена неправильно.

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

4. Рассматривали ли вы возможность использования AVG() функции?

5. Если я вас правильно понимаю, для каждого имени N вам нужна СУММА (count) / M, где M — количество месяцев, в которых фактически есть количество для имени N ?

Ответ №1:

Если вам нужно среднее значение за месяц, вы можете СГРУППИРОВАТЬ ПО имени и месяцу и использовать функцию AVG:

 SELECT `name`, `month`, avg(`count`)
FROM table 
WHERE `category` ='something' AND `month` NOT LIKE 'May'
GROUP BY `name`, `month`;
  

Если вам нужно среднее значение за весь период, просто СГРУППИРУЙТЕ ПО имени и среднему количеству:

 SELECT `name`, avg(`count`)
FROM table 
WHERE `category` ='something' AND `month` NOT LIKE 'May' 
GROUP BY `name`;
  

И другой вариант, если вам не нравится AVG :

 SELECT `name`, sum(`count`)/(SELECT count(*) FROM `table` AS `t2` WHERE `category` ='something' AND `month` NOT LIKE 'May' and `t1`.`name` = `t2`.`name`) 
FROM `table` AS `t1` 
WHERE `category` ='something' AND `month` NOT LIKE 'May')
GROUP BY name;
  

Но я бы остался с AVG .

На самом деле, я предпочитаю использовать != вместо NOT LIKE , это улучшает читаемость

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

1. Я бы использовал функцию average. Но моя проблема заключается в следующем. В базе данных может быть много записей за один и тот же месяц. Январь может появляться пятнадцать раз, февраль десять и так далее. Для моей цели мне нужно среднее количество в месяц. Если я использую функцию avg, не получает ли она средние значения по количеству записей?

2. И если нет, то все равно будет получено среднее значение только по количеству месяцев, которые действительно появляются? Например, Алекс появился через один месяц, поэтому его среднее значение должно быть просто этим значением, потому что его следует разделить на единицу. Мэри следует разделить на три. Джон на четыре (потому что только с января по апрель).

3. @user3794422 Нет, он будет разделяться только на количество элементов в группе, а не на общее количество. Таким образом, вы можете использовать его (или, по крайней мере, протестировать, чтобы увидеть, работает ли он)

4. Большое тебе спасибо, чувак. Да, я проверил это. Это то, что я должен был сделать, прежде чем подвергать сомнению его достоинства. Это работает как шарм. Я приношу извинения форуму, если этот вопрос уже был задан. Однако я не смог найти никаких дубликатов. Еще раз, спасибо Uriil и всем остальным, кто ответил. Амин, тебе тоже спасибо. Я ценю это.

5. Не знаю, что такое подзапрос. Поэтому я не могу комментировать, если это кажется «излишним». Я не хочу беспокоить вас вопросом, почему это плохо, если у вас нет на это времени. 🙂 приветствуется любая помощь.

Ответ №2:

Просто для полноты вот РАБОЧАЯ СКРИПКА. использование функции AVG — это правильный путь, поскольку она будет выполнять среднее значение на человека в месяц. посмотрите на Джона в январе .. его результат равен 5,5, когда количество (в январе) равно 5 и 6 .. среднее значение = 5,5.

 SELECT 
  person, 
  month, 
  avg(counter)
FROM testing 
where 
(
  category ='something' 
  AND month <> 'May'
) 
GROUP BY person, month;
  

Если вы хотите просмотреть данные в одном, как это звучит в вашем сообщении, тогда вы можете сделать это. ЕЩЕ ОДНА СКРИПКА

 SELECT
    person,
    group_concat(month),
    group_concat(average_count)
FROM(
    SELECT 
      person, 
      month, 
      avg(counter) as average_count
    FROM testing 
    where 
    (
      category ='something' 
      AND month <> 'May'
    ) 
    GROUP BY person, month
      ) as t
group by person;
  

Ответ №3:

Попробуйте это :

 SELECT name, SUM(count) / COUNT(DISTINCT month)
FROM table
WHERE month != 'May'
AND category = 'something'
GROUP BY name
  

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

1. Это тоже работает. Он генерирует те же результаты, что и Uriils. Его второй код на самом деле делает то же самое, что и этот? Это странно, потому что он сказал, что это будет на весь период. В любом случае оба работают…

2. Ни в коем случае его второй запрос не выполняет то же самое, что и этот. Пожалуйста, прочитайте мои комментарии к его ответу.