2012-09-06 2 views
0

나는 나의 숙제를했고, 그물에와 StackOverflow의 정보를 찾았하지만 내 질문에 대한 답을 찾지 못했습니다.의 MySQL이보다 테이블 A로 조인 스마트/더 좋은 방법의 결과에 열로 테이블 B의 행을 얻기?

How to Display rows as Columns in MySQL?

:

Creating two colums from rows of a table (그것을 이해하지 못했다) MySQL join same table display rows in columns way (complicated) 내 쿼리를 작성하려면이 옵션을 사용 Creating two colums from rows of a table

(다른과 문제가 동일하지 않는 것) : 나는 보았다 나는 이런 식으로 진행되는 테이블 "수업"을 가지고있다 :

ID title 
--------- 
1 Math 
2 Latin 
3 English 
4 Science 

나는 테스트 사용자의 유형을 저장하는 두 번째 표 "결과는"각 레슨 통과해야합니다. 현재 두 가지 유형의 테스트가 있습니다 : o 및 w (향후 더 많을 수 있음). 표는 다음과 같습니다 :

lesson_id usr_id test_type course_id 
---------------------------------------- 
1   100  o   1 
1   100  w   1 
1   24  o   1 
1   36  w   1 

위의 표에서 사용자 100은 테스트 O 및 W를 통과했습니다. 위의 표에서 사용자 24는 수학 테스트를 통과했습니다. 위의 표에서 사용자 36은 수학을 위해 테스트 w를 통과했습니다. 사용자 36

ID title  o  w 
------------------------------ 
1 Math  TRUE TRUE 
2 Latin  FALSE FALSE 
3 English FALSE FALSE 
4 Science FALSE FALSE 

:

이제

I 사용자 (100)에 대한 보고서를 좀하고 싶습니다, 내가 좋아하는 뭔가를하고 싶은

ID title  o  w 
------------------------------ 
1 Math  TRUE FALSE 
2 Latin  FALSE FALSE 
... 
: 사용자 24

ID title  o  w 
------------------------------ 
1 Math  FALSE TRUE 
2 Latin  FALSE FALSE 
... 

다른 사용자 :

다음과 같이 921,751,

내가 쿼리로이 작업을 수행 할 수 있습니다 : 그것은 두 가지를 필요로 조인 각이 만들어 조인 때문에

SELECT l.id, l.title, COALESCE(s.o,FALSE) AS o, COALESCE(t.w, FALSE) AS w FROM lessons l 
LEFT JOIN (
    SELECT r.lesson_id, 
    CASE 
     WHEN r.test_type='o' THEN TRUE 
     ELSE FALSE 
    END AS o 
    FROM results r WHERE r.itype='o' AND r.usr_id=100 
    ) AS s ON l.id=s.lesson_id 
LEFT JOIN (
    SELECT rr.lesson_id, 
    CASE 
     WHEN rr.test_type='w' THEN TRUE 
     ELSE FALSE 
    END AS w 
    FROM results rr WHERE rr.test_type='w' AND rr.usr_id=100 
    ) AS t ON l.id=t.lesson_id 
WHERE l.course_id=1 ORDER BY l.id ASC; 

를이 코드는 (여전히 바쁜 시험을) 작동하는 것 같다 동안, 나는 그것을 좋아하지 않아 장래에 꽤 큰 것으로 판명 될 수있는 표를 선택합니다. 이 쿼리는 (더 똑똑 의미 할 수있다, 더 간단하게, 빠르게 또는 기타 디자인 ... 또는 :-) 다른 제안)

  1. 은 당신이 할 수있는 더 좋은 방법을 제안 할 수 있습니다 자주 실행할 것인가?

    나는이 고수해야 할 경우
  2. , 당신은 빨리이 쿼리를 실행하는 가장 좋은 인덱스를 설정하는 방법으로 참조하는 것이 좋습니다 수 있을까? 사용한 링크, 기사?

  3. 은 무엇보다 test_types를 생성 할 위치는 어떻게됩니까? 내 쿼리는 w와 o 만 사용합니다. 내일이면 더 많은 것이 있습니까? 이런 종류의 일을하는 일반적인 방법이 있습니까?어떤 도움/조언을 환영합니다 이상입니다

,

필립

답변

0

나는이 간단한 집계 쿼리로 참조하십시오. 집계는 lesson_id 및 title을 기준으로합니다. 가입 인해 왼쪽 외부에

select l.lesson_id, l.title, 
     max(case when r.test_type = 'o' then 'TRUE' else 'FALSE' end) as o, 
     max(case when r.test_type = 'w' then 'TRUE' else 'FALSE' end) as w 
from lessons l left outer join 
    results r 
    on l.lesson_id = r.lesson_id 
where r.user_id = <whatever> 
group by l.lesson_id, l.title 
order by 1 

그것이 NULL이 될 수 있습니다 결과에서 온해야하기 때문에 문제가이 수준에서 사용자에 의해 선택 : 계산은 단지 O 및 w에 대한 결과를 선회.

select l.lesson_id, l.title, 
     max(case when r.test_type = 'o' then 'TRUE' else 'FALSE' end) as o, 
     max(case when r.test_type = 'w' then 'TRUE' else 'FALSE' end) as w 
from lessons l left outer join 
    results r 
    on l.lesson_id = r.lesson_id and 
     r.user_id = <whatever> 
group by l.lesson_id, l.title 
order by 1 

절 "의"우리는 모든 수업이 유지 될 것이라는 보장을 조건으로 이동하여 : 여기에 문제를 해결 변형이다.

+0

확인하고 좀 더 질문 : 1.In의 경우 사용자가 위의 예에서와 같이 100 만 첫 번째 행 보인다 반환되는 (o와 ww가 참인 경우). 이상적으로, 저는 다른 모든 수업도하고 싶습니다. 다시 수업에 참여할 것입니다. 그러나 그것은 하나 더 작게 만들 것입니다. 2. 나는 max(), 재미있는 것을 이해한다. 하지만 그룹별로 주문한 이유를 설명해 주시겠습니까? 감사. –

+0

Magnifique! 그것은 작동합니다. SQL에 대한 더 많은 독서가 도움이 될 것 같습니다. "SQL과 Excel을 사용한 데이터 분석"이 그 길을 가고 있습니다. 많은 감사합니다. –

1

다른 데이터베이스에서는 수행하려는 작업을 PIVOT이라고합니다. 아쉽게도 MySQL에는 집계 함수가 없으므로 집계 함수와 CASE 문을 사용해야합니다. 당신은 당신이 모르는 의미 동적으로 수행하려는 경우

select l.id, 
    l.title, 
    max(case when test_type = 'o' then 'true' else 'false' end) as o, 
    max(case when test_type = 'w' then 'true' else 'false' end) as w 
from lessons l 
left join results r 
    on l.id = r.lesson_id 
    and r.usr_id = 100 -- the user id will change for each person 
group by l.id, l.title 

이제 SQL Fiddle with Demo

를 참조하십시오 : 당신은 당신이 두 test_type 값을 알고있는 경우

는, 당신은 하드 코딩이 할 수있는

Dynamic pivot tables (transform rows to columns)

: test_types의 수는 전치 시간의 앞서가, 당신은 다음 문서를 검토해야

귀하의 코드는 다음과 같습니다

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'MAX(CASE WHEN test_type = ''', 
     test_type, 
     ''' THEN ''true'' ELSE ''false'' END) AS ', 
     test_type 
    ) 
) INTO @sql 
FROM Results; 


SET @sql 
    = CONCAT('SELECT l.id, 
     l.title, ', @sql, ' 
    from lessons l 
    left join results r 
     on l.id = r.lesson_id 
     and r.usr_id = 100 
    group by l.id, l.title'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

내가 쿼리를 시도 SQL Fiddle with Demo

관련 문제