1

私は、データが次のように格納されている恐ろしく設計されたテーブルを継承しました。

Period |  Identifier |   Value
----------------------------------
1      | AB1         | some number
1      | AB2         | some number
1      | AB3         | some number
1      | AB4         | some number
1      | AB5         | some number
1      | A1          | some number
1      | A2          | some number
1      | A3          | some number
1      | A4          | some number
1      | A5          | some number
2      | AB1         | some number
2      | AB2         | some number
2      | AB3         | some number
2      | AB4         | some number
2      | AB5         | some number
2      | A1          | some number
2      | A2          | some number
2      | A3          | some number
2      | A4          | some number
2      | A5          | some number

データを次の形式に変換するSELECTステートメントを使用しようとしています。

Row # | First value | Second value
1     | A1's number | AB1's number     // The next 5 rows are data from period 1
2     | A2's number | AB2's number
3     | A3's number | AB3's number
4     | A4's number | AB4's number
5     | A5's number | AB5's number
6     | A1's number | AB1's number     // These 5 rows are from period 2
7     | A2's number | AB2's number
8     | A3's number | AB3's number
9     | A4's number | AB4's number
10    | A5's number | AB5's number

AB%A%はその形式の2つの別々のIDであり、条項を少し苛立たせているWHERE LIKE ...と思います。データを希望の形式に強制できるかどうかは完全にはわかりませんが、上司から調査を依頼されました。

SQLコードがわからない私の最初の試みは、行番号自体を調べて作業することでしたが、私が言ったように、そのルートをどのように進めるかがわかりません。

現在、データはSQL Serverにありますが、SASからを使用してアクセスされますproc sqlDECLAREこれらの標準は、サポートされていなくても、ほとんどの部分でSQLServerに準拠していると思います。

いいえ、この方法でデータを保存することが誰のアイデアであったかはわかりません...

4

3 に答える 3

2

識別子の「B」がタイプAとタイプABの識別子を区別するためにのみ使用される場合は、その文字を削除して結果を結合するだけです。

SELECT ROW_NUMBER() OVER(ORDER BY AData.Period, AData.[Identifier]) AS [Row #]
    , AData.[Identifier] AS [First Value]
    , ABData.[Identifier] AS [Second Value]
FROM YourTable AData
-- Change to a LEFT JOIN if not all A's have AB's.
JOIN YourTable ABData
    -- NOTE: Assumes that 'B' is the only differentiator between
    -- AData and ABData's Identifier column and that it is
    -- not repeated as part of the common identifier.
    ON AData.[Identifier] = REPLACE(ABData.[Identifier], 'B', '')

あなたは絶対に正しいです-それはひどく素晴らしいスキーマではありません-これはおそらく全表スキャンを必要とするでしょう。

于 2012-10-25T21:42:06.257 に答える
2

SASを使用している場合は、PROCTRANSPOSEを使用します。データを取得して、データの移動先の変数を決定するラベル変数を含めます。

data datatable;
infile datalines dlm='|';
input
Period Identifier $ Value $;
datalines;
1      | AB1         | some number
1      | AB2         | some number
1      | AB3         | some number
1      | AB4         | some number
1      | AB5         | some number
1      | A1          | some number
1      | A2          | some number
1      | A3          | some number
1      | A4          | some number
1      | A5          | some number
2      | AB1         | some number
2      | AB2         | some number
2      | AB3         | some number
2      | AB4         | some number
2      | AB5         | some number
2      | A1          | some number
2      | A2          | some number
2      | A3          | some number
2      | A4          | some number
2      | A5          | some number
;;;
run;

data have;
set datatable;
idlabel = compress(identifier, ,'d');
byval = compress(identifier,,'kd');
run;

proc sort data=have;
by period byval;
run;
proc transpose data=have out=want;
by period byval;
id idlabel;
var value;
run;

何らかの理由でSQLで実行する必要がある場合は、それ自体への結合として実行するのが最善です。ABとAの両方でperiod=1およびcompress(identifier ,,'kd')= 1である行を結合する必要があるため、次のように実行できます。

proc sql;
  create table want as 
    select A.period, AB.value as AB, A.value as A
    from (select * from have where compress(identifier,,'d')='AB') AB, 
         (select * from have where compress(identifier,,'d')='A') A
    where AB.period=A.period
    and compress(AB.identifier,,'kd') = compress(A.identifier,,'kd');
quit;

しかし、PROC TRANSPOSEオプションは、自己結合よりも効率的である可能性が高いと思います(データが表示されているほどきれいでない場合は、より柔軟になります)。

于 2012-10-25T21:45:01.493 に答える
2

特定の期間にわたってAをABに1秒間関連付けるというトリッキーさを無視して、データを何らかの方法で関連付けることができた場合は、テーブルで内部結合を実行して、探している形式を選択します。

SELECT row_number() OVER(ORDER BY a.Period, a.Identifier, b.Identifier), 
       a.Value, 
       b.Value 
FROM TableName a 
  INNER JOIN TableName b ON join_mechanism 
ORDER BY a.Period, a.Identifier, b.Identifier

ここで、結合メカニズムを埋めるために、明らかな部分はa.Period=b.Periodを持つことです。疑わしい部分は、このテキストが静的である場合に文字列の置換を試みる可能性があるという考えです。したがって、REPLACE(a.Identifier、'A'、'AB')=b.Identifier。

したがって、すべてのことを言って、あなたは持っているでしょう:

SELECT row_number() OVER(ORDER BY a.Period, a.Identifier, b.Identifier), 
       a.Value, 
       b.Value 
FROM TableName a 
  INNER JOIN TableName b ON a.Period = b.Period AND REPLACE(a.Identifier, 'A', 'AB') = b.Identifier 
ORDER BY a.Period, a.Identifier, b.Identifier

注:SELECTステートメントはテストされていません。使用しているのは、row_numberをサポートする比較的新しいバージョンのMSSQLであると想定しています。

于 2012-10-25T21:55:07.933 に答える