1

我有两个具有一对多关系的表,可以说我有这个。

**Table Owners**
K  Owner
1  Fred
2  Jason
3  Tonya

Table Cars

K CarBrand
1 Mitsubishi 
1 Honda
1 VW
2 Toyota
3 Ford

而不是得到这个:

K Owner CarBrand 
1 Fred  Mitsubishi 
1 Fred  Honda
1 Fred  VW

我想用这样的结果进行查询:

K Owner CarBrand1 CarBrand2 Carbrand3
1 Fred  Mitsubishi Honda     VW

我怎样才能做到这一点?

4

2 回答 2

2

不是真的,但这很接近

Select k, owner, group_concat(carbrand)
FROM owners, cars
WHERE
owner.k = cars.k
GROUP BY car brand

对不起格式,我会解决的。

于 2012-11-15T19:32:21.633 回答
2

看起来您想将数据从单列、多行转换为多列和每人一行。这基本上是一个PIVOT但不幸的是 MySQL 没有PIVOT函数,因此您需要使用带有CASE语句的聚合函数来复制它。

如果您知道您将拥有多少个汽车品牌,您可以对这些值进行硬编码,如下所示:

select k, owner,
  max(case when nameRn = 'CarBrand1' then carbrand end) CarBrand1,
  max(case when nameRn = 'CarBrand2' then carbrand end) CarBrand2,
  max(case when nameRn = 'CarBrand3' then carbrand end) CarBrand3
from
(
  select k, owner, carbrand,
    concat('CarBrand', @num := if(@owner = `owner`, @num + 1, 1)) as nameRn,
    @owner := `owner` as dummy
  from
  (
    select k, owner, carbrand, @rn:=@rn+1 overall_row_num
    from
    (
      select o.k, o.owner, c.carbrand
      from owners o
      inner join cars c
        on o.k = c.k
      order by carbrand
    ) oc, (SELECT @rn:=0) r
    order by k 
  ) r
) src
group by k, owner

请参阅带有演示的 SQL Fiddle

但是,如果您有未知数量的值,那么您可以使用准备好的语句来生成它的动态版本:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when nameRn = ''',
      nameRn,
      ''' then carbrand end) AS ',
      nameRn
    )
  ) INTO @sql
FROM 
(
  select k, owner, carbrand,
    concat('CarBrand', @num := if(@owner = `owner`, @num + 1, 1)) as nameRn,
    @owner := `owner` as dummy
  from
  (
    select k, owner, carbrand, @rn:=@rn+1 overall_row_num
    from
    (
      select o.k, o.owner, c.carbrand
      from owners o
      inner join cars c
        on o.k = c.k
      order by carbrand
    ) oc, (SELECT @rn:=0) r
    order by k 
  ) r
) src;


SET @sql = CONCAT('SELECT k, owner, ', @sql, ' 
                  from
                  (
                    select k, owner, carbrand,
                      concat(''CarBrand'', @num := if(@owner = `owner`, @num + 1, 1)) as nameRn,
                      @owner := `owner` as dummy
                    from
                    (
                      select k, owner, carbrand, @rn:=@rn+1 overall_row_num
                      from
                      (
                        select o.k, o.owner, c.carbrand
                        from owners o
                        inner join cars c
                          on o.k = c.k
                        order by carbrand
                      ) oc, (SELECT @rn:=0) r
                      order by k 
                    ) r
                  ) src
                   GROUP BY k, owner');

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

请参阅带有演示的 SQL Fiddle

结果将与两者相同:

| K | OWNER | CARBRAND1 | CARBRAND2 |  CARBRAND3 |
--------------------------------------------------
| 1 |  Fred |        VW |     Honda | Mitsubishi |
| 2 | Jason |    Toyota |    (null) |     (null) |
| 3 | Tonya |      Ford |    (null) |     (null) |
于 2012-11-15T19:33:07.987 回答