SQL Group by - выберите оба столбца
Вопрос
У меня есть таблица пользователей, содержащих следующие столбцы:
| User_ID (int) | Name (varchar) | Age (int) | Experience_Level (int) |
Я хотел бы создать запрос SQL для вывода всех идентификаторов людей, которые не являются уникальными в сочетании возраста и опыта.
Мой код до сих пор:
SELECT Count(*), User_ID FROM Users
GROUP BY Age,Experience_Level
HAVING Count(*) > 1
Очевидно, что это неполное, это будет группа не уникальных пользователей, но он не скажет мне все их user_ids.
Заранее спасибо за вашу помощь!
Решение
Вот отрицательный логический запрос:
SELECT *
FROM Users
WHERE UserID not in
(
SELECT MIN(UserID)
FROM Users
GROUP BY Age, Experience_Level
HAVING COUNT(*) = 1
)
Другие советы
Поскольку вы хотите получить информацию о группах нескольких пользователей, как вы хотите, чтобы эти данные были возвращены? В строке, содержащем Comma-разделенный список значений user_id?
Вы не пометили свой вопрос с маркой SQL базы данных, которые вы используете.
Если вы используете MySQL или SQLite, вы можете использовать встроенный GROUP_CONCAT()
Функция:
SELECT Count(*), GROUP_CONCAT(User_ID) AS User_List FROM Users
GROUP BY Age,Experience_Level
HAVING Count(*) > 1
По умолчанию, GROUP_CONCAT()
отделяет значения запятыми. Обратитесь к руководству, если вы хотите, чтобы он отформатировал другой путь.
Есть и другие решения для других поставщиков SQL. Этот вопрос пришел много раз на переполнении стека:
SELECT t.User_ID, t.Age, t.Experience_Level
FROM Users t INNER JOIN
(SELECT Age, Experience_Level
FROM Users
GROUP BY Age, Experience_Level
HAVING Count(*) > 1) d ON t.Age = d.Age AND t.Experience_Level = d.Experience_Level
Тестовый скрипт:
create table Users (
User_ID int,
Name varchar(50),
Age int,
Experience_Level int
)
insert into Users (User_ID, Name, Age, Experience_Level) values (1, 'A', 33, 1)
insert into Users (User_ID, Name, Age, Experience_Level) values (2, 'B', 37, 1)
insert into Users (User_ID, Name, Age, Experience_Level) values (3, 'C', 33, 1)
insert into Users (User_ID, Name, Age, Experience_Level) values (4, 'D', 35, 2)
insert into Users (User_ID, Name, Age, Experience_Level) values (5, 'E', 33, 1)
insert into Users (User_ID, Name, Age, Experience_Level) values (6, 'F', 35, 2)
insert into Users (User_ID, Name, Age, Experience_Level) values (7, 'G', 18, 1)
Теоретически, что вы хотите, это что-то подобное, но, к сожалению, SQL Server не позволяет ему:
SELECT * FROM Users
WHERE (Age, Experience_Level) IN
(
SELECT Age, Experience_Level
FROM Users
GROUP BY Age,Experience_Level
HAVING Count(*) > 1
)
Таким образом, вместо этого вы должны согласиться на присоединение к подзапросу:
SELECT Users.* FROM Users
INNER JOIN
(
SELECT Age, Experience_Level
FROM Users
GROUP BY Age,Experience_Level
HAVING Count(*) > 1
) subq
ON Users.Age = subq.Age
AND Users.Experience_Level = subq.Experience_Level