2012-04-29 4 views
3

예/아니오 설문 조사 질문에 대한 MySQL 응답 표가 있습니다. 같이 좀 보이는 :행 사이의 값을 비교하고 평균 응답을 찾는 방법은 무엇입니까?

| user_id | poll_id | response | 
|------------|----------|-----------| 
| 111  | 1  | 'yes' | 
| 111  | 2  | 'no' | 
| 111  | 3  | 'no' | 
| 222  | 1  | 'yes' | 
| 222  | 2  | 'yes' | 
| 222  | 3  | 'yes' | 
| 333  | 1  | 'no' | 
| 333  | 2  | 'no' | 
| 333  | 3  | 'no' | 

나는 각 사용자의 반응과 다른 모든 사용자의 응답 사이의 유사성을 계산하고 싶습니다. 따라서 사용자 111과 사용자 222는 0.333 (3 개의 동일한 응답 중 1 개를 가지고 있기 때문에) 유사하며 사용자 111과 사용자 333은 유사합니다 (3 개의 동일한 응답 중 2 개가 있기 때문에). 에,

SELECT COUNT(*) AS same_count 
FROM (
      SELECT response 
      FROM results 
      WHERE user_id = 111 
     ) AS t1 
    , (
      SELECT response 
      FROM results 
      WHERE user_id = 222 
     ) AS t2 
WHERE t1.response = t2.response 

지금은 모든 사용자에게 그 정보를 얻을 수있는 방법을 알아 내려고 노력하고있어 나는이 지정된 사용자 나에게 같은 응답 수를 줄 것이다 쿼리를 작성했습니다

중복 정보없이, 가능하다면,

| user_1 | user_2 | same_count | 
|---------|----------|--------------| 
| 111 | 222 | 0.333  | 
| 111 | 333 | 0.666  | 
| 222 | 111 | 0.333  | 
| 222 | 333 | 0   | 
| 333 | 111 | 0.666  | 
| 333 | 222 | 0   | 

을 또는 :이 같은 결과를

| user_1 | user_2 | same_count | 
|---------|----------|--------------| 
| 111 | 222 | 0.333  | 
| 111 | 333 | 0.666  | 
| 222 | 333 | 0   | 

내 g을 ut은 PHP에서 루프를 통해 많은 쿼리를 수행 할 필요없이 단일 괴물 같은 MySQL 쿼리로이를 수행 할 수있는 방법이 있음을 알립니다. 누구든지 올바른 방향으로 나를 가리킬 수 있습니까?

+0

당신이 정말로 크기가 사용자 테이블의 제곱있는 테이블을 하시겠습니까? 테이블 크기의 정사각형 함수로 계산 및 크기를 사용하면 많은 사용자가있을 경우 문제가 발생할 수 있습니다. –

답변

1

이해야 당신이 원하는 결과를 얻을 :

SELECT 
    t1.user_id AS user_1, 
    t2.user_id AS user_2, 
    SUM(CASE WHEN t1.response = t2.response THEN 1 ELSE 0 END)/COUNT(1) 
    AS same_count 
FROM t t1 
JOIN t t2 ON (t2.user_id > t1.user_id AND t2.poll_id = t1.poll_id) 
GROUP BY t1.user_id, t2.user_id 
ORDER BY user_1, user_2 

내 테스트 결과 :

111 222 0.333333333333333 
111 333 0.666666666666667 
222 333 0 

CASE 부분 (t1.response = t2.response), 내 버전으로 MySQL의에서 쉽게 작성할 수 있습니다 다른 유형의 데이터베이스에서도 작동합니다.
이 부분은 일치하는 모든 항목을 세어 항목 수로 나눔으로써 주요 트릭을 수행합니다.

t2.user_id > t1.user_id은 중복 (111-222, 222-111)을 제거합니다.

3

* poll_id * 및 * user_id * 열을 사용하여 동일한 테이블에서 완전 외부 조인을 수행해야합니다. 결과는 두 번 표시되고 별칭 1 테이블의 user_id 값이 별칭 2 테이블의 값보다 작은 값만 결과 집합에 포함되는 방식으로 조건을 지정해야하는 것을 방지해야합니다.

Click here to view the demo in SQL Fiddle.

스크립트 :

CREATE TABLE poll 
(
    user_id  INT   NOT NULL 
    , poll_id  INT   NOT NULL 
    , response VARCHAR(10) NOT NULL 
); 

INSERT INTO poll (user_id, poll_id, response) VALUES 
    (111, 1, 'yes'), 
    (111, 2, 'no'), 
    (111, 3, 'no'), 
    (222, 1, 'yes'), 
    (222, 2, 'yes'), 
    (222, 3, 'yes'), 
    (333, 1, 'no'), 
    (333, 2, 'no'), 
    (333, 3, 'no'); 

SELECT  p1.user_id AS user_1 
     , p2.user_id AS user_2, 
      AVG(CASE 
        WHEN p1.response = p2.response THEN 1 
        ELSE 0 
       END) Average_Response 
FROM  poll p1 
,   poll p2 
WHERE  p1.poll_id = p2.poll_id 
AND   p1.user_id < p2.user_id 
GROUP BY p1.user_id 
     , p2.user_id; 

출력 :

USER_1 USER_2 AVERAGE_RESPONSE 
------ ------ ---------------- 
111  222  0.3333 
111  333  0.6667 
222  333  0 
관련 문제