0

次の行を返す簡単なクエリがあります。

現在の行:

Empl    ECode   DCode       LCode       Earn    Dedn    Liab
====    ====    =====       =====       ====    ====    ====
123     PerHr   Null        Null        13      0       0
123     Null    Union       Null        0       10      0
123     Null    Per         Null        0       20      0
123     Null    Null        MyHealth    0       0       5
123     Null    Null        401         0       0       10
123     Null    Null        Train       0       0       15
123     Null    Null        CAFTA       0       0       20

ただし、上記の行を次のように表示する必要がありました。

Empl    ECode   DCode   LCode       Earn    Dedn    Liab
====    ====    =====   =====       ====    ====    ====
123     PerHr   Union   MyHealth    13      10      5
123     Null    Per     401         0       20      10
123     Null    Null    Train       0       0       15
123     Null    Null    CAFTA       0       0       20

EarnCodeこれは、、、DednCodeおよびのNullが検出された場合は常に、後続の行を先行する行にマージするようなものLiabCodeです。実際に私が見たかったのは、すべてを前の行にロールアップすることでした。

OracleにはこのLAST_VALUE関数を使用できましたが、この場合、これをどうすればよいかわかりません。

上記の例では、ECodeの合計値の列はEarn、、、、およびです。、、、またはのいずれかがnullでない場合は常に、、、または列に対応する値があることに注意してください。DCodeDednLCodeLiabECodeDCodeLCodeEarnDednLiab

ちなみに、SQL Server2008R2を使用しています。

あなたのアドバイスを期待して、ありがとう。

4

3 に答える 3

1

これは基本的に Tango_Guy と同じ手法ですが、一時テーブルがなく、並べ替えが明示的に行われています。Empl ごとの行数 <= 既に配置されている行数であるため、左端のテーブルのダミー テーブルを作成する必要はなく、3 つのコード間で一致する場所にベース データをフィルター処理するだけです。また、あなたの議論を確認し、Earn と ECode は一緒に動きます。実際、ECode のない列のゼロ以外の Earn は実質的に失われます (これは制約の適切なケースです - ECode が NULL の場合、ゼロ以外の Earn は許可されません)。

http://sqlfiddle.com/#!3/7bd04/3

CREATE TABLE data(ID INT IDENTITY NOT NULL,
                  Empl VARCHAR(3), 
                  ECode VARCHAR(8), 
                  DCode VARCHAR(8), 
                  LCode VARCHAR(8),
                  Earn INT NOT NULL,
                  Dedn INT NOT NULL,
                  Liab INT NOT NULL ) ;

INSERT INTO data (Empl, ECode, DCode, LCode, Earn, Dedn, Liab)
VALUES ('123', 'PerHr', NULL, NULL, 13, 0, 0),
        ('123', NULL, 'Union', NULL, 0, 10, 0),
        ('123', NULL, 'Per', NULL, 0, 20, 0),
        ('123', NULL, NULL, 'MyHealth', 0, 0, 5),
        ('123', NULL, NULL, '401', 0, 0, 10),
        ('123', NULL, NULL, 'Train', 0, 0, 15),
        ('123', NULL, NULL, 'CAFTA', 0, 0, 20);

WITH basedata AS (
    SELECT *, ROW_NUMBER () OVER(ORDER BY ID) AS OrigSort, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY ID) AS EmplSort
    FROM data
),
E AS (
  SELECT Empl, ECode, Earn, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY OrigSort) AS EmplSort
  FROM basedata
  WHERE ECode IS NOT NULL
),
D AS (
  SELECT Empl, DCode, Dedn, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY OrigSort) AS EmplSort
  FROM basedata
  WHERE DCode IS NOT NULL
),
L AS (
  SELECT Empl, LCode, Liab, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY OrigSort) AS EmplSort
  FROM basedata
  WHERE LCode IS NOT NULL
)
SELECT basedata.Empl, E.ECode, D.Dcode, L.LCode, E.Earn, D.Dedn, L.Liab
FROM basedata
LEFT JOIN E
    ON E.Empl = basedata.Empl AND E.EmplSort = basedata.EmplSort
LEFT JOIN D
    ON D.Empl = basedata.Empl AND D.EmplSort = basedata.EmplSort
LEFT JOIN L
    ON L.Empl = basedata.Empl AND L.EmplSort = basedata.EmplSort
WHERE E.ECode IS NOT NULL OR D.DCode IS NOT NULL OR L.LCode IS NOT NULL
ORDER BY basedata.Empl, basedata.EmplSort
于 2012-08-15T04:44:06.257 に答える
0

私には解決策がありますが、それは非常に厄介です。誰かがもっと良いものを持っていれば、それは素晴らしいことです。

ただし、アルゴリズム:

1) 列の個別の値リストごとに行番号を取得する
2) 行番号に基づいてすべての列を結合する

例:

select Distinct ECode   into #Ecode     from source_table   order by rowid;
select Distinct DCode   into #Dcode     from source_table   order by rowid;
select Distinct LCode   into #Lcode     from source_table   order by rowid;
select Distinct Earn    into #Earn  from source_table   order by rowid;
select Distinct Dedn    into #Dedn  from source_table   order by rowid;
select Distinct Liab    into #Liab  from source_table   order by rowid;

select b.ECode, c.DCode, d.LCode, e.Earn, f.Dedn, g.Liab
from source_table   a -- Note:  a source for row numbers that will be >= the below
left outer join #Ecode b on a.rowid = b.rowid
left outer join #DCode c on a.rowid = c.rowid
left outer join #LCode d on a.rowid = d.rowid
left outer join #Earn  e on a.rowid = e.rowid
left outer join #Dedn  f on a.rowid = f.rowid
left outer join #Liab  g on a.rowid = g.rowid
where 
    b.ecode is not null or
    c.dcode is not null or
    d.lcode is not null or
    e.earn is not null or
    f.dedn is not null or
    g.liab is not null;

あなたがどのような役割を果たしたいのかわからないので、Empl は含めませんでした。これが特定の Empl にすべて当てはまる場合は、それを追加して結合し、実行することができます。

私はこの解決策がまったく好きではないので、他の誰かがもっとエレガントなものを考え出すことを願っています.

ベスト、デビッド

于 2012-08-15T04:11:01.220 に答える
0

それが必要なものかどうかはわかりませんが、coalesc を試しましたか

SELECT Name, Class, Color, ProductNumber,
COALESCE(Class, Color, ProductNumber) AS FirstNotNull
FROM Production.Product ;
于 2012-08-15T03:57:49.940 に答える