자체로 테이블에 참여, 그룹 :
+----------+--------+
| project | person |
+----------+--------+
| datamax | Jimmy |
| datamax | Ashley |
| datamax | Martin |
| cocoplus | Jimmy |
| cocoplus | Ashley |
| glassbox | Jimmy |
| glassbox | Martin |
| powerbin | Jimmy |
| powerbin | Ashley |
+----------+--------+
이 결과는 다음과 같이 보일 것입니다 person
필드 :
SELECT u2.person, COUNT(u1.project) AS collaborations
FROM users u1
JOIN users u2 ON u2.project = u1.project
WHERE u1.person != u2.person AND u1.person = 'Jimmy'
GROUP BY u2.person;
쿼리는 Ji mmy는 u1
에서 참가했습니다. u2
의 행은 u1
의 행으로 필터링됩니다. 두 표의 사용자가 일치하는 중복 항목은 WHERE
절로 필터링됩니다. 마지막으로 결과 집합은 person
으로 그룹화되고 COUNT
함수는 그룹 당 행 수를 계산합니다.
성능
주, person
및 project
열 (또는 두 개의 인덱스)에 대한 지수는 크게 위의 쿼리의 성능이 향상됩니다. 특정 인덱스 구성은 테이블 구조에 따라 다릅니다. 차라리에서 사람과 프로젝트를 저장하는 것,
그러나
ALTER TABLE users ADD INDEX `project` (`project`(10));
ALTER TABLE users ADD INDEX `person` (`person`(10));
정규화 :하지만, 나는 다음과 같은 예를 들어, person
및 project
두 varchar
필드가있는 테이블에 대한 매우 충분하다 생각 숫자 ID가있는 별도의 표. 세 번째 테이블은 커넥터 역할을 할 수 있습니다 : person_id - project_id
. 즉, 나는 normalization을 추천합니다. 정규화 된 테이블을 사용하면 텍스트 필드에 비 대한 인덱스를 작성할 필요가 없습니다. 로 보일 수 있습니다
정규화 된 테이블은 다음과 같습니다
CREATE TABLE users (
id int unsigned NOT NULL AUTO_INCREMENT,
name varchar(200) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
-- This index is needed, if you want to fetch users by names
INDEX name (name(8))
);
CREATE TABLE projects (
id int unsigned NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY(`id`)
);
CREATE TABLE collaborations (
project_id int unsigned NOT NULL DEFAULT 0,
user_id int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY(`project_id`, `user_id`)
);
모양 정규화 된 구조에 대한 쿼리 더 복잡한 조금 :
-- In practice, the user ID is retrieved from the calling process
-- (such as POST/GET HTTP requests, for instance).
SET @user_id := (SELECT id FROM users WHERE name LIKE 'Jimmy');
SELECT u.name person, COUNT(p.id) collaborations
FROM collaborations c
JOIN collaborations c2 USING(project_id)
JOIN users u ON u.id = c2.user_id
JOIN projects p ON p.id = c2.project_id
WHERE c.user_id = @user_id AND c.user_id != c2.user_id
GROUP BY c2.user_id;
그러나 빨리 될 것이며, 필요한 공간 특히 대용량 데이터 세트의 경우 인덱스가 상당히 작아집니다.
원래 대답
은 각 사람을위한 프로젝트의 총 수를 가져 GROUP BY
절 COUNT
기능을 사용하려면 :이 사람들과 협업 수의 테이블을 리턴
SELECT person, COUNT(*) AS collaborations
FROM users
GROUP BY person;
,하지만은 않습니다 사람을 지정하지 않고 계산합니까? 나는 모든 공동 작업자와 한 사람의 수를 찾고 있습니다. – Rachie
@Rachie, [this] (http://sqlfiddle.com/#!9/c92a8/1)을 확인하십시오. 답변을 업데이트했습니다. –