2013-07-10 2 views
1

이것이 가능한지 확실치 않으며 설명하기가 어렵습니다.선택 내에서 서브 쿼리

나는이 방법으로 SELECT 쿼리를 반환하고 싶습니다

: tbl_option_fields tbl_person tbl_person_optionals

첫 번째 테이블은 단순히 무제한 선택적 필드를 정의

 
pID | Name | Email   | Dog Name | Fish Name 
------------------------------------------------------- 
44 | John | [email protected] | Scruffy | 
56 | Jane | [email protected] |   | Puffer 
72 | Joe | [email protected] | Sparky | Gill 

3 개 테이블이 있습니다.

 
optid | opttitle 
------------------ 
1  | Dog Name 
2  | Fish Name 
3  | Email 

두 번째 표는 단순히 내가 사람들을 위해 데이터를 보관 :

 
pID | Name 
--------------- 
44 | John 
56 | Jane 
72 | Joe 

마지막 테이블의 날이 pID

 
ID | pID | optid | optval 
---------------------------------- 
1 | 44 | 1 | Scruffy 
2 | 56 | 2 | Puffer 
3 | 72 | 1 | Sparky 
4 | 72 | 2 | Gill 
5 | 72 | 3 | [email protected] 
6 | 56 | 3 | [email protected] 
7 | 44 | 3 | [email protected] 
을 위해 존재하는 임의의 데이터를 저장할 수 여기에 열은

SELECT 문의 결과는 결과의 헤더에 opttitle을 표시해야합니다. 하위 쿼리가 좋지 않습니다.이 쿼리는 좋지 않을 수 있습니다.

여기 내 시도입니다 :

SELECT p.*, opt.optval 
FROM `tbl_person` p 
LEFT OUTER JOIN `tbl_person_optionals` opt ON p.pID = opt.pID 
WHERE 1 

이 쿼리 결과를 복제의 원인, 그리고 내가 이유를 이해 믿습니다.

 
pID | Name | optval    
----------------------------- 
44 | John | [email protected] 
44 | John | Scruffy 

56 | Jane | [email protected] 
56 | Jane | Puffer 

72 | Joe | [email protected] 
72 | Joe | Sparky 
72 | Joe | Gill 

는 다행스럽게도 필자는 차라리 행에서 새로운 기록보다 수평 옵션 필드를 표시하도록 설명하고있다. 이 작업을 수행 할 수 있습니까?

+1

당신이 찾고있는 것은 피벗 쿼리이지만, mysql은이를 지원하지 않습니다. 해결 방법이 있지만 추악한 구문으로 만들어지며 피벗 된 결과에 더 많은 열을 추가하거나 추가 할 때 자동으로 확장되지 않습니다. –

+0

그리고 그것은 아마도 내가 듣고 싶어했던 것입니다. 감사! – coffeemonitor

답변

0

기본적으로 원하는 것은 피벗 테이블입니다. 이것은 this article describes in full, glorious detail과 같은 MySQL에서 할 수 있습니다.

그러나, 당신이 당신의 테이블 tbl_option_fields당신이 가진 모든 옵션을 SELECT - 연산자를 추가해야 당신이 당신의 현재 테이블 디자인 할 archieve하기 위해서이다. 몇 가지 옵션 만 있으면 관리가 가능하지만 옵션이 많을수록 성명서가 더 복잡해지고 결국 수행 속도가 느려집니다.

또 다른 단점은 새로운 옵션이 생길 때마다 명세서를 조정해야한다는 것입니다.

기본적으로 함께 거주하거나 테이블 디자인을 조정해야합니다. 몇 가지 옵션이 더있을 수 있지만 그 두 가지로 귀결됩니다.

0

여기에 하나 개의 솔루션입니다 :

SELECT p.pID, p.Name, 
    MAX(IF(opt.optid=3, opt.optval, NULL)) AS `Email`, 
    MAX(IF(opt.optid=1, opt.optval, NULL)) AS `Dog Name`, 
    MAX(IF(opt.optid=2, opt.optval, NULL)) AS `Fish Name` 
FROM `tbl_person` p 
LEFT OUTER JOIN `tbl_person_optionals` opt ON p.pID = opt.pID 
GROUP BY p.pID; 

당신은 모든 optid의를 알고 있어야하고이 쿼리를 작성 전에 열 레이블을 지정합니다. 이것은 MySQL에도 해당되지만 네이티브 PIVOT 명령을 지원하는 RDBMS 브랜드 (예 : Microsoft SQL Server)에도 해당됩니다. SQL은 데이터 검사를 시작하기 전에 쿼리의 열을 정의해야합니다. 쿼리는 개별 데이터 값을 발견 할 때 더 많은 열을 "추가"할 수 없습니다.

따라서 선택적 필드를 정의하는 첫 번째 테이블을 쿼리하고 결과를 사용하여 위의 SQL 쿼리를 동적으로 작성해야합니다.

대안은 예제에서 보여준 것처럼 행을 하나씩 가져와 행을 가져와 모든 행을 가져 와서 사람 당 한 행으로 다시 배열하는 것입니다.

어느 쪽이든 : 동적 피벗 쿼리를 사용하면 쿼리 전에 또는 쿼리 후에 더 많은 응용 프로그램 코드를 작성해야합니다.

0

당신은 결과를 함께 테이블을 조인하고 집계하여이 작업을 수행 할 수 있습니다 :

select po.pid, p.name, 
     MAX(case when o.optId = 'Email' then po.optval end) as Email, 
     MAX(case when o.optId = 'Dog Name' then po.optval end) as DogName, 
     MAX(case when o.optId = 'Fish Name' then po.optval end) as FishName 
from tbl_person_optionals po join 
    tbl_person p 
    on p.pId = p.pId join 
    tbl_optionfields o 
    on p.optid = o.optid 
group by po.pid, p.name; 

이렇게하면 열에서 원하는 것을 알고 있다고 가정합니다. Select 문은 고정 된 열 집합 만 반환 할 수 있으므로 tbl_optionfields에 각 값에 대해 별도의 열을 반환하려면 동적 SQL (즉 prepare 문 사용)이 필요합니다.