Выбирать только уникальные записи из нескольких столбцов

#mysql #sql

#mysql #sql

Вопрос:

У меня есть таблица, в которой регистрируются загрузки по IP, версии и платформе. Просматривая таблицу вручную, я вижу множество дубликатов, где все 3 из этих значений одинаковы. (пользователь, вероятно, просто нетерпелив) Я хотел бы использовать оператор SELECT, который отфильтровывает дубликаты и возвращает только одну из записей, если все 3 из этих значений одинаковы. Еще более продвинутый вариант, если это возможно, у меня также есть поле даты / времени, которое использует CURRENT_TIMESTAMP. Было бы неплохо, если бы я мог включить дубликаты, если они относятся к разным дням, но не к разным временам. Таким образом, я могу видеть, загружает ли тот же пользователь снова в другой день.

В основном я просто пытаюсь получить статистику о том, сколько уникальных людей загружают каждую версию каждый день. Структура таблицы БД проста…

ключ (АВТО_ИНКРЕМЕНТ), дата (CURRENT_TIMESTAMP), ip, пользователь_агент, платформа, версия

Программное обеспечение имеет версию (платформу) для Windows и Mac, и я предлагаю как текущую версию, так и несколько отличных прошлых версий, которые были до серьезных изменений.

Ответ №1:

Просто сгруппируйте по полям, которые вы хотите исключить из дублирования, например

 SELECT ip, platform, version, COUNT(*) AS number_of_tries, max(download_date) AS last_download_date 
FROM downloads
GROUP BY ip, platform, version, DATE(download_date)
  

Тогда было бы относительно легко выполнить более сложную фильтрацию по группировке результатов по дням и т.д.

Ответ №2:

mysql версии 8.0 , которую вы можете использовать row_number()

 select * from (select *,
row_number()over(partition by ip,platform,date(datetime) order by datetime) rn
       from table_name 
) a where a.rn=1
  

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

1. Похоже, что мой хост использует 5.7. Есть ли аналогичный способ сделать это в более низких версиях?

2. @Dan нет, это доступно с 8 в mysql

Ответ №3:

Это то, чего вы хотите? Он возвращает первую запись на каждую дату для комбинации ip / platform / version :

 select t.*
from <tablename> t
where t.datetime = (select min(t2.datetime)
                    from <tablename> t2
                    where t2.ip = t.ip and
                          t2.platform = t.platform and
                          t2.version = t.version and
                          date(t2.datetime) = date(t.datetime)
                   );
  

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

1. Я должен это протестировать, но, похоже, это именно то, что я хочу

2. Хорошо, извините за основной вопрос, но я не могу понять, что на самом деле использовать для t и t2. Имя таблицы — ‘downloads’. Я заменил все экземпляры ‘t’ на ‘downloads’, но я не уверен, что делать с t2. Я попытался просто оставить его как t2, но я получаю 0 строк. SQL на самом деле не моя сильная сторона. Я использую это время от времени, но я в основном разработчик C / C , поэтому я никогда не делаю ничего большего, чем базовый тип SELECT / INSERT.