2

表 1 には NameId、age、gender...
表 2 には Version No、TimeStamp ... があります。

今、テーブル 1 から NameId を選択し、テーブル 2 からバージョン番号とタイムスタンプを複数回選択したいのですが、テーブル 2 からすべてのバージョンと時刻のレコードを照会する必要があります。

NameId  |   Version/Time        |   Version/Time    |   Version/Time …

Angela  |    1  /  01.01.2010   |   2 / 01.02.2010  |   3 / 01.03.2010
Betty   |    1  /  01.01.2010   |   2 / 01.02.2010  |   3 / 01.03.2010
Cathy   |    1  /  01.01.2010   |   2 / 01.02.2010  |   3 / 01.03.2010
...     |   ....                |                   |   
4

2 に答える 2

0

通常のアプローチは、2 つのテーブル間で JOIN を実行することです。

SELECT t1.NameId
     , t2.VersionNo
     , t2.Timestamp
  FROM table_one t1
  LEFT
  JOIN table_two t2
    ON t2.NameId = t1.NameId
 ORDER
    BY t1.NameId
     , t2.VersionNo

これにより、次のような結果セットが得られます。

NameId   VersionNo TimeStamp
-------- --------- ----------
Angela   1         01.01.2010   
Angela   2         01.02.2010  
Angela   3         01.03.2010
Betty    1         01.01.2010   
Betty    2         01.02.2010  
Betty    3         01.03.2010
Cathy    1         01.01.2010   
Cathy    2         01.02.2010  
Cathy    3         01.03.2010

(これはNameId 値によってtable_two関連付けられていると仮定します。元の質問で提供されたサンプル データでは、これが 3 つの行で各行と一致する可能性が残されています(つまり、デカルト積)。その場合、それはステートメント内の CROSS JOIN:table_onetable_twotable_one

SELECT t1.NameId
     , t2.VersionNo
     , t2.Timestamp
  FROM table_one t1
 CROSS
  JOIN table_two t2
 ORDER
    BY t1.NameId
     , t2.VersionNo

そのクエリからの結果セットを「クロス集計」(またはピボット テーブル) に変換し、各行をtable_two同じ出力行に表示するには、通常、SQL ステートメントではなくクライアントで処理する方が適切です。

ただし、MySQL は、各 VersionNo と Timestamp の値が別々の列にある同様の結果セットを返す可能性があります。しかし、それを行うためのクエリは自明ではありません。

(簡単な代替手段の 1 つは GROUP_CONCAT 集計関数を使用することですが、これは個別の列ではなく単一の列を返し、. によって制限されmax_allowd_packet_sizeます。)

SELECT t1.NameID
     , GROUP_CONCAT(CONCAT(t2.VersionNo,'/',t2.Timestamp) ORDER BY t2.VersionNo)
  FROM table_one t1
  LEFT
  JOIN table_two t2
    ON t2.NameId = t1.NameId
 GROUP
    BY t1.NameId
 ORDER
    BY t1.NameId

table_twoこれが に関連していると仮定するとtable_one、かなり扱いにくいが簡単に理解できるアプローチの 1 つは、クエリの SELECT リストで相関サブクエリを使用することです。

SELECT t1.NameId
     , ( SELECT CONCAT(t2a.VersionNo,' / ',t2a.Timestamp)
           FROM table_two t2a WHERE t2a.NameId = t1.NameID
          ORDER BY t2a.VersionNo LIMIT 0,1 
       ) AS `Version/Time`
     , ( SELECT CONCAT(t2b.VersionNo,' / ',t2b.Timestamp)
           FROM table_two t2b WHERE t2b.NameId = t1.NameID
          ORDER BY t2b.VersionNo LIMIT 1,1 
       ) AS `Version/Time`
     , ( SELECT CONCAT(t2c.VersionNo,' / ',t2c.Timestamp)
           FROM table_two t2c WHERE t2c.NameId = t1.NameID
          ORDER BY t2c.VersionNo LIMIT 2,1
       ) AS `Version/Time`
  FROM table_one t1
 ORDER BY t1.NameId

そのクエリは、元の質問に示されているものと同様の結果セットを返しますが、返される列の数は SELECT ステートメント内で静的に定義されています。

于 2012-12-07T21:39:17.137 に答える
0

あなたが言うように、固定値セットが機能しない場合は、ピボットを行うために動的SQLが必要になります。

これらの行に沿って何か:

CREATE PROCEDURE [dbo].[usp_pivot_]
AS

DECLARE @columns VARCHAR(1000)

SELECT @columns = COALESCE(@columns + ',[' + cast(versionTime as varchar) + ']',
'[' + cast(versionTime as varchar)+ ']')
FROM table1 inner join table2 on table1.NameId = table2.NameId
GROUP BY versionTime 

DECLARE @query VARCHAR(8000)

SET @query = '
SELECT *
FROM table1 inner join table2 on table1.NameId = table2.NameId
PIVOT
(
first(versionTime)
FOR [versionTime]
IN (' + @columns + ')
)
AS p'

EXECUTE(@query)
于 2012-12-07T20:01:46.847 に答える