-2

重複の可能性:
2番目のテーブルを1つの行に「フラット化」する必要がある2つのテーブル(1-Mの関係)を結合します

SQLコースの紹介をしましたが、現時点ではこれを理解できません。

私は2つのテーブルを持っています:

表1:

    user_id date  value
    ids     dates values

表2:

    user_id user_names
    ids     names

次の結果を表示するMYSQLクエリが必要です。

    /   name1  name2  name3 etc
  date1 val1-1 val1-2 val1-3 
  date2 val2-1 val2-2 val2-3

それをする方法があるのを覚えていますよね?どんな助けでもいただければ幸いです。

4

3 に答える 3

1

この方法でデータを回転させることをピボットと呼びます。残念ながら、MySQLにはピボット関数がないため、集計関数とCASE式を使用して複製する必要があります。

サンプルデータ:このクエリに使用

CREATE TABLE Table1
    (`user_id` int, `date` datetime, `value` int)
;

INSERT INTO Table1
    (`user_id`, `date`, `value`)
VALUES
    (1, '2013-01-01 00:00:00', 100),
    (2, '2013-01-01 00:00:00', 200),
    (1, '2013-01-02 00:00:00', 500)
;

CREATE TABLE Table2
    (`user_id` int, `user_names` varchar(4))
;

INSERT INTO Table2
    (`user_id`, `user_names`)
VALUES
    (1, 'John'),
    (2, 'Tim')
;

列に変換するすべての値(たとえば、names)がわかっている場合は、それらをハードコーディングすると、SQLは次のようになります。

select 
  date,
  max(case when rownum = 1 then value end) as John,
  max(case when rownum = 2 then value end) as Tim
from
(
  select date, value, user_names,
    @row:=case when @prev=date then @row else 0 end + 1 as rownum,
    @prev:=date 
  from
  (
    select t1.date, t1.value, t2.user_names
    from table1 t1
    inner join table2 t2
      on t1.user_id = t2.user_id
    order by date, user_names
  ) d, (SELECT @row:=0, @prev:=null) r
  order by date, user_names
) src
group by date

SQL FiddlewithDemoを参照してください。ご覧のとおり、日付内の各名前に行番号を割り当てるためにユーザー変数を実装する必要がありました。これにより、列に変換する個別の名前の値がいくつあるかがわかります。

ただし、状況によっては、各日付の名前の数が不明であるため、プリペアドステートメント内で動的SQLを使用する必要があります。

この場合、コードは次のようになります。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when rownum = ',
      rownum,
      ' then value end) AS `',
      user_names, '`'
    )
  ) INTO @sql
from
(
  select date, value, user_names,
    @row:=case when @prev=date then @row else 0 end + 1 as rownum,
    @prev:=date 
  from
  (
    select t1.date, t1.value, t2.user_names
    from table1 t1
    inner join table2 t2
      on t1.user_id = t2.user_id
    order by date, user_names
  ) d, (SELECT @row:=0, @prev:=null) r
  order by date, user_names
) src;


SET @sql = CONCAT('SELECT date, ', @sql, ' 
                  from
                  (
                    select date, value, user_names,
                      @row:=case when @prev=date then @row else 0 end + 1 as rownum,
                      @prev:=date 
                    from
                    (
                      select t1.date, t1.value, t2.user_names
                      from table1 t1
                      inner join table2 t2
                        on t1.user_id = t2.user_id
                      order by date, user_names
                    ) d, (SELECT @row:=0, @prev:=null) r
                    order by date, user_names
                  ) src
                  group by date');

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

SQL FiddlewithDemoを参照してください。どちらのバージョンでも結果が得られます。

|                           DATE | JOHN |    TIM |
--------------------------------------------------
| January, 01 2013 00:00:00+0000 |  100 |    200 |
| January, 02 2013 00:00:00+0000 |  500 | (null) |
于 2013-01-30T10:50:34.983 に答える
0

内部結合を使用して2つのテーブルを結合し、ビューとして保存します。次に、これを生データとして使用して、結果セットをピボットすると、目的の結果が得られます。結合、ビューの作成、およびPIVOTには、すべてSOに関する大量のコード例が含まれている必要があり、コース終了後に簡単に実行できる必要があります。

于 2013-01-30T05:08:31.927 に答える
0

はい、それを行う方法があります............その呼ばれるピボットテーブル

これを参考にしてください。

MySQLピボットテーブル(行を列に変換)

于 2013-01-30T05:15:58.317 に答える