MySQL 피벗 행을 동적 열 수로


81

세 가지 MySQL 테이블이 있다고 가정 해 보겠습니다.

products:

id | name
 1   Product A
 2   Product B

partners:

id | name
 1   Partner A
 2   Partner B

sales:

partners_id | products_id
          1             2
          2             5
          1             5
          1             3
          1             4
          1             5
          2             2
          2             4
          2             3
          1             1

행에 파트너가 있고 열에 제품이있는 테이블을 얻고 싶습니다. 지금까지 다음과 같은 출력을 얻을 수있었습니다.

name      | name      | COUNT( * )
Partner A   Product A          1
Partner A   Product B          1
Partner A   Product C          1
Partner A   Product D          1
Partner A   Product E          2
Partner B   Product B          1
Partner B   Product C          1
Partner B   Product D          1
Partner B   Product E          1

이 쿼리 사용 :

SELECT partners.name, products.name, COUNT( * ) 
FROM sales
JOIN products ON sales.products_id = products.id
JOIN partners ON sales.partners_id = partners.id
GROUP BY sales.partners_id, sales.products_id
LIMIT 0 , 30

하지만 대신 다음과 같은 것을 갖고 싶습니다.

partner_name | Product A | Product B | Product C | Product D | Product E
Partner A              1           1           1           1           2
Partner B              0           1           1           1           1

문제는 내가 가질 제품 수를 알 수 없으므로 제품 테이블의 행에 따라 열 번호가 동적으로 변경되어야한다는 것입니다.

이 아주 좋은 대답은 mysql에서 작동하지 않는 것 같습니다. T-SQL Pivot? 행 값에서 테이블 열 생성 가능성


여러 제안에 대해서는 행에서 열로 링크를 참조하십시오 .
Bhavin Pokiya


@BhavinPokiya는 여러분이 제공 한 MS SQL-Server 링크이고 이것은 MySQL로 태그가 지정되어 있습니다.
MattSom

답변:


107

불행히도 MySQL에는 PIVOT기본적으로 수행하려는 기능 이 없습니다 . 따라서 CASE문과 함께 집계 함수를 사용해야합니다 .

select pt.partner_name,
  count(case when pd.product_name = 'Product A' THEN 1 END) ProductA,
  count(case when pd.product_name = 'Product B' THEN 1 END) ProductB,
  count(case when pd.product_name = 'Product C' THEN 1 END) ProductC,
  count(case when pd.product_name = 'Product D' THEN 1 END) ProductD,
  count(case when pd.product_name = 'Product E' THEN 1 END) ProductE
from partners pt
left join sales s
  on pt.part_id = s.partner_id
left join products pd
  on s.product_id = pd.prod_id
group by pt.partner_name

SQL 데모 보기

제품을 모르기 때문에 동적으로 수행하고 싶을 것입니다. 이것은 준비된 명령문을 사용하여 수행 할 수 있습니다.

동적 피벗 테이블 (행을 열로 변환)을 사용하면 코드는 다음과 같습니다.

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'count(case when Product_Name = ''',
      Product_Name,
      ''' then 1 end) AS ',
      replace(Product_Name, ' ', '')
    )
  ) INTO @sql
from products;

SET @sql = CONCAT('SELECT pt.partner_name, ', @sql, ' from partners pt
left join sales s
  on pt.part_id = s.partner_id
left join products pd
  on s.product_id = pd.prod_id
group by pt.partner_name');

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

SQL 데모 보기

GROUP_CONCAT기본적으로 1024 바이트로 제한 된다는 점에 주목할 가치가 있습니다. 시술 기간 동안 더 높게 설정하여이 문제를 해결할 수 있습니다.SET @@group_concat_max_len = 32000;


2
"max_len"에 관한 마지막 코멘트는 생명의 은인이었습니다! 팁 고마워.
Edward

1
보다 동적 인 피벗 쿼리를 찾고 있다면 다음을 확인하십시오 : boynux.com/creating-pivot-reports-in-mysql
Boynux

제품 이름은 어떻게됩니까ProductA') from partners pt; truncate partners;
avatarofhope2

@ avatarofhope2 이것은 질문입니까, 암시입니까? 이것이 사출 각도를 제공한다면 그것을 처리하는 적절한 방법은 무엇입니까?
MattSom
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.