php select count distinct

Mysql: полезный трюк с count() и count(distinct)

Хочу поделиться одним интересным решением, к которому мне удалось прийти сегодня во время оптимизации запроса поиска пользователей. В выборке необходимо было возвращать количество общих групп текущего пользователя и меня — того, кто производит поиск. Что называется total shared groups. В итоге всё поместилось в один компактный запрос без подзапросов (что очень критично, позже объясню почему) с использованием одной таблицы в FROM, без GROUP BY и HAVING.

Представим задачу более наглядно. Примем следующие таблицы:
— group (group_id)
— user (user_id)
— user_group (хранит связки user_id-group_id)

Необходимо узнать количество групп, в котором состоят пользователи user1 и user2. То есть найти пересечения между юзерами по таблице user_group.

1. Следующий запрос выдаст количество всех записей из таблицы user_group, которые принадлежат юзерам user1 и user2.
SELECT
COUNT(`group_id`)
FROM
`user_group`
WHERE
`user_id` IN (:user1,:user2)

2. А вот этот запрос выдаст количество записей из таблицы user_group, которые принадлежат юзерам user1 и user2, но с уникальным group_id:
SELECT
COUNT(DISTINCT `group_id`)
FROM
`user_group`
WHERE
`user_id` IN (:user1,:user2)

В данном случае, если нашлись такие группы, которые были привязаны сразу к двум нашим пользователям, то они будут «схлопнуты» в одну строку.

Если отнять общее число групп двух пользователей и число групп, с учётом уникальности group_id, то в рузультате получим наше искомое total shared groups — сколько общих групп у двух пользователей.

Как ещё можно было решить задачу?
SELECT
COUNT(*)
FROM
(
SELECT
`group_id`
FROM
`user_group`
WHERE
`user_id` IN (:user1,:user2)
GROUP BY
`group_id`
HAVING
COUNT(*) > 1
) as `shared_groups`

Такой подход я встречал довольно часто. Но у него есть один существенный минус — использование подзапроса. Если :user1 или :user2 не передаются в запрос, а подставляются динамически из запроса верхнего уровня (например, какой-нибудь `user1`.`user_id`), то данный вариант выдаст ошибку.

Источник

SELECT COUNT(DISTINCT name), id, adress from users

With PHP I’m trying to run a SQL query and select normal columns as well as COUNT.

The problem is that when I have «COUNT(DISTINCT name),» in my query, it will only return the first entry. When I remove it, it will return all matching entries from the db.

I could separate it and do 2 queries, but I’m trying to avoid this due to performance concerns.

What do I make wrong? thx, Mexx

6 Answers 6

The ability to mix normal columns and aggregate functions is a (mis)feature of MySQL. You can even read why it’s so dangerous on MySQL’s documentation: https://dev.mysql.com/doc/refman/5.6/en/group-by-extensions.html

But if you really want to mix normal rows and a summary in a single query, you can always use the UNION statement:

COUNT() is an aggregate function, it aggregates against the results of the rest of your query. If you want to count all distinct names, and not just the distinct names associated with the id and address that you are selecting, then yes, you will have to run two queries. That’s just how SQL works.

Note that you should also have a group by clause when aggregating. I think the fact that MySQL doesn’t require it is horrible, and it encourages really bad habits.

From what I understand, you want to get :

This is not quite possible, I’d say.

A solution would be, like you said, two queries.

. Or, in your case, you could do the count on the PHP side, I suppose.
ie, not count in the query, but use an additionnal loop in your PHP code.

Источник

SELECT, SELECT DISTINCT. Вывод данных из таблиц в MySQL

Команда SELECT

SELECT используется для создания выборок из базы данных MySQL.

С помощью SELECT можно:

Синтаксис запроса вывода данных из таблицы

Вывод данных таблицы в терминале

Пример вывода данных колонок id, title, author, price, amount из таблицы books.

mysql> USE Bookstore;
Database changed

mysql> SELECT id, title, author, price, amount FROM books;
+—-+—————————+———————+———+———+
| id | title | author | price | amount |
+—-+—————————+———————+———+———+
| 1 | Дубровский (Акция) | Александр Пушкин | 230.00 | 20 |
| 2 | Нос (Акция) | Николай Гоголь | 255.20 | 7 |
| 3 | Мастер и Маргарита | Михаил Булгаков | 263.00 | 8 |
| 4 | Мёртвые души (Акция) | Николай Гоголь | 173.00 | 3 |
| 5 | Преступление и наказание | Фёдор Достоевский | 245.00 | 3 |
| 6 | Война и мир | Лев Толстой | 341.00 | 1 |
| 7 | Анна Каренина | Лев Толстой | 346.00 | 0 |
| 8 | Отцы и дети | Иван Тургенев | 371.00 | 3 |
| 9 | Собачье сердце | Михаил Булгаков | 232.00 | 10 |
| 10 | Бесы | Фёдор Достоевский | 212.00 | 8 |
+—-+—————————+———————+———+———+
10 rows in set (0.00 sec)

Запрос для вывода данных всех колонок из таблицы books, будет выглядеть так.

Вывод данных можно также организовать не только в виде таблицы, но и в виде списка, просто добавьте флаг \G после имени таблицы.

mysql> SELECT * FROM books \G;
*************************** 1. row ***************************
id: 1
title: Дубровский (Акция)
author: Александр Пушкин
genre: Драма,Повесть
price: 230.00
discount: 15
edition: 1
isbn: 841-6-817-134484-1
page_num: 120
publish_year: 1855
creation_date: 2019-01-28 15:17:12
amount: 20
shelf_position: f4a322ccca

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

Если у вас есть несколько связанных таблиц, то с помощью SELECT вы можете выводить их данные составляя из них одну таблицу.

Выведем колонки id, book_id и status для таблицы orders.

Выведем колонки title, author, price из таблицы books и колонку status из таблицы orders.

mysql> SELECT title, author, price, status FROM books, orders WHERE books.id=book_id;
+———————+——————-+———+——————+
| title | author | price | status |
+———————+——————-+———+——————+
| Мастер и Маргарита | Михаил Булгаков | 263.00 | Новый |
| Дубровский (Акция) | Александр Пушкин | 230.00 | Обрабатывается |
+———————+——————-+———+——————+
2 rows in set (0.00 sec)

Вывести колонки с одинаковыми именами, например id, в данном случае не получится, т.к. они имеются в обоих таблицах.

Команда SELECT DISTINCT

Источник

SQL Инструкция SELECT DISTINCT

SQL SELECT DISTINCT

Инструкция SELECT DISTINCT используется для возврата только определенных значений.

Внутри таблицы столбец часто содержит множество повторяющихся значений; иногда требуется только перечислить различные (определенные) значения.

Синтаксис SELECT DISTINCT

Демо базы данных

Ниже приведена выборка из таблицы «клиенты» в базе данных Northwind:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

Выбрать без DISTINCT

Следующая инструкция SQL выбирает все (включая дубликаты) значения из столбца «страна» в таблице «клиенты»:

Пример

Теперь давайте используем ключевое слово DISTINCT с приведенным выше оператором SELECT и посмотрим результат.

Выбрать с DISTINCT

Следующая инструкция SQL выбирает только отдельные значения из столбца «страна» в таблице «клиенты»:

Пример

Следующая инструкция SQL перечисляет количество различных (определенных) стран клиентов:

Пример

Примечание: приведенный выше пример не будет работать в Firefox и Microsoft Edge! Потому что COUNT (DISTINCT column_name) не поддерживается в базах данных Microsoft Access. Firefox и Microsoft Edge используют Microsoft Access в наших примерах.

Источник

SQL-Урок 11. Выборка уникальных данных (SELECT DISTINCT)

Оператор SQL DISTINCT используется для указания на то, что следует работать только с уникальными значениями столбца.

Оператор SQL DISTINCT нашел широкое применение в операторе SQL SELECT, для выборки уникальных значений. Так же используется в агрегатных функциях.

Синтаксис

Примеры

Все примеры будут по этой таблице workers, если не сказано иное:

idnameagesalary
1Дима23400
2Петя25500
3Вася23500
4Коля301000
5Иван27500
6Кирилл281000

Пример

Давайте выберем все уникальные значения зарплат из таблицы workers:

SQL запрос выберет следующие строки:

salary
400
500
1000

Пример

Давайте подсчитаем все уникальные значения зарплат из таблицы workers (их будет 3 штуки: 400, 500 и 1000):

SQL запрос выберет следующие строки:

Пример

Давайте подсчитаем одновременно все уникальные значения зарплат и уникальные значения возрастов и запишем их в разные поля:

SQL запрос выберет следующие строки:

salary_countage_count
35

Пример

Давайте просуммируем все уникальные значения зарплат из таблицы workers:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *