MYSQL select-запрос со сложной логикой

#php #mysql

#php #mysql

Вопрос:

У меня есть некоторые данные об агентах, голосующих за разные варианты в разное время:

  ------------ ------------- ------ ----- --------- ---------------- 
| Field      | Type        | Null | Key | Default | Extra          |
 ------------ ------------- ------ ----- --------- ---------------- 
| ID         | int(10)     | NO   | PRI | NULL    | auto_increment |
| option     | varchar(50) | NO   |     | NULL    |                |
| agent      | varchar(50) | NO   |     | NULL    |                |
| date       | datetime    | NO   |     | NULL    |                |
 ------------ ------------- ------ ----- --------- ---------------- 
  

Теперь я хотел бы вывести все строки, в которых по крайней мере a агентов проголосовали по крайней мере в t дат за один из не более o вариантов.

Итак, предположим, например, a = 2, t = 3, o = 1. Затем я хочу вывести только те строки, сумма которых равна (count)>= 3 * 2 и в которых по крайней мере для 3 разных дат являются голосования за один из не более 1 варианта из 2 разных агентов. Например.:

Команда выбора, которую я ищу, должна выводиться из:

  -------- ------- ------ 
| option | agent | date |
 -------- ------- ------ 
|  opt1  |   a   |   1  |
|  opt1  |   a   |   2  |
|  opt1  |   a   |   3  |
|  opt2  |   b   |   1  |
|  opt2  |   b   |   2  |
|  opt2  |   b   |   3  |
|  opt1  |   c   |   1  |
|  opt1  |   c   |   2  |
|  opt1  |   c   |   3  |
 -------- ------- ------ 
  

Только строки агента a и c:

  -------- ------- ------ 
|  opt1  |   a   |   1  |
|  opt1  |   a   |   2  |
|  opt1  |   a   |   3  |
|  opt2  |   b   |   1  |
|  opt1  |   c   |   1  |
|  opt1  |   c   |   2  |
|  opt1  |   c   |   3  |
 -------- ------- ------ 
  

Есть ли способ сделать это или мне нужно выполнить набор комбинаций через скрипт (PHP)? Большое спасибо, Кристиан

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

1. Я несколько смущен вашими требованиями. Можете ли вы добавить еще несколько этапов к своему описанию. Я не понимаю, почему агент b находится в конечных результатах один раз, когда все 3 их записи кажутся одинаковыми, или это только опечатка?

2. Для меня это путаница: «проголосовал по крайней мере в t дат за один из не более o вариантов». является ли 0 опечаткой?

3. Спасибо за ваши комментарии! @Kickstart: мне очень жаль — строка с агентом b в выходных данных неверна. ad Len_D: «o» обозначает количество опций. На самом деле, я мог бы упростить логику запроса, в котором я нуждаюсь, следующим образом: показать все строки так, чтобы для строк a * t были агенты A1, …, Aa , даты T1, …, Tt и опции O1, …, Oo , такие, что каждый из агентов выбирает для каждой даты по одному выходуиз опций O1, …, Oo . …

4. ad Kickstart и @Len_D: в PHP-скрипте я бы пробежался по всем подмножествам набора дат с ровно t элементами и вывел бы все эти подмножества, где пересечение всех агентов, выбирающих на некоторую дату в подмножестве, имеет по крайней мере элементы и где объединение опций, выбранных с помощьюточно агенты имеют не более o элементов. Но проблема в том, что эта процедура занимает довольно много времени и с более чем 2500 датами невозможно выполнить.

Ответ №1:

Думаю, вам понадобится пара вложенных запросов. Один, чтобы получить все параметры / агенты с как минимум таким количеством дат, сколько требуется, а затем использовать это в качестве источника для другого запроса, чтобы найти количество опций с как минимум требуемым количеством агентов. Затем объедините результаты этого запроса с вашей таблицей, чтобы получить подробную информацию об этих параметрах.

 SELECT sometable.`option`, sometable.agent, sometable.date
FROM
(
    SELECT `option`, COUNT(DISTINCT agent) as distinct_agents
    FROM
    (
        SELECT `option`, agent, COUNT(DISTINCT date) AS distinct_dates 
        FROM sometable
        GROUP BY `option`, agent
        HAVING distinct_dates >= 3
    ) sub0
    GROUP BY `option`
    HAVING distinct_agents >=2
) sub1
INNER JOIN sometable
ON sub1.`option` = sometable.`option`
  

SQL-скрипка для него:-

http://www.sqlfiddle.com /#!2/2e357/2