2017-07-27 1 views
0

私は頭痛を与えているテーブルに行がないことに問題があります。基本データとしてシーケンス内の行を順序付けし、行が見つからない場合は空白を埋めてください

、私は、次の表を持っている:

declare @table table 
(
    id1 int, 
    id2 int, 
    ch char(1) not null, 
    val int  
) 

insert into @table values (1112, 121, 'A', 12) 
insert into @table values (1351, 121, 'A', 13) 
insert into @table values (1411, 121, 'B', 81) 
insert into @table values (1312, 7, 'C', 107) 
insert into @table values (1401, 2, 'A', 107) 
insert into @table values (1454, 2, 'D', 107) 
insert into @table values (1257, 6, 'A', 1) 
insert into @table values (1269, 6, 'B', 12) 
insert into @table values (1335, 6, 'C', 12) 
insert into @table values (1341, 6, 'D', 5) 
insert into @table values (1380, 6, 'A', 3) 

出力ID2によって順序付けし、次ID2が開始されるまで繰り返すべき、CHの固定された順序に従うべきです。

id1  id2  ch  val 
----------------------------  
1112 121  'A' 12 
NULL 121  'B' NULL 
NULL 121  'C' NULL 
NULL 121  'D' NULL 
1351 121  'A' 13 
1411 121  'B' 81 
NULL 121  'C' NULL 
NULL 121  'D' NULL 
NULL 7  'A' NULL 
NULL 7  'B' NULL 
1312 7  'C' 107 
NULL 7  'D' NULL 
1401 2  'A' 107 
NULL 2  'B' NULL 
NULL 2  'C' NULL 
1454 2  'D' 107 

など:

シーケンス:私はこの結果テーブルを取得するよう

'A' 
'B' 
'C' 
'D' 

シーケンスやパターンが中断された場合は、それは、ヌルで不足している行を埋める必要があります。 ..

私が探しているのは、反復なしでこれを行う方法です。

私は誰かが助けることを願っています!

ありがとうございます!

答えて

1

ソリューションは、このようになります。

declare @table table ( id1 int, id2 int, ch char(1) not null, val int ) 
insert into @table values (1112, 121, 'A', 12) 
    ,(1351, 121, 'A', 13),(1411, 121, 'B', 81),(1312, 7, 'C', 107),(1401, 2, 'A', 107) 
    ,(1454, 2, 'D', 107),(1257, 6, 'A', 1),(1269, 6, 'B', 12),(1335, 6, 'C', 12) 
    ,(1341, 6, 'D', 5),(1380, 6, 'A', 3) 
;with foo as 
(select 
    * 
    ,row_number() over (partition by id2 order by id1) rwn 
    ,ascii(isnull(lag(ch,1) over (partition by id2 order by id1),'A'))-ascii('A') prev 
    ,count(*) over (partition by id2,ch) nr 
    ,ascii(ch)-ascii('A') cur 
from @table 

) 
,bar as 
(
select 
*,case when cur<=prev and rwn>1 then 4 else 0 end + cur-prev step 
from foo 
) 
,foobar as 
(
select *,sum(step) over (partition by id2 order by id1 rows unbounded preceding) rownum 
from bar 
) 
,iterations as 
(
select id2,max(nr) nr from foo 
group by id2 
) 
,blanks as 
(
select 
id2,ch chnr,char(ch+ascii('A'))ch,ROW_NUMBER() over (partition by id2 order by c.nr,ch)-1 rownum,c.nr 
from iterations a 
inner join (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) c(nr) 
on c.nr<=a.nr 
cross join (values (0),(1),(2),(3)) b(ch) 
) 
select 
b.id1,a.id2,a.ch,b.val 
from blanks a 
left join foobar b 
on a.id2=b.id2 and a.rownum=b.rownum 
order by a.id2,a.rownum 

まず、行番号を調べ、id2ごとにchの前の値を取得するクエリ「foo」を作成します。

"bar"は、行間に欠損値がいくつあるかを検出します。例えば前のものがA、現在のものがcの場合は2があります。前のものがA、現在のものがAならば4です!

"foobar"はステップを追加し、元の行に番号を付けて最終出力に配置します。

「反復」は、「ABCD」行が表示される回数をカウントします。

「BLANKS」は、すべての最後の行であることが、各ID2のためである、それは最終的な出力にする必要があり、すべての「ABCD」の行を出力し、ROWNUMで数字それらを

は最後に、私は「参加左foob​​ar "とid2と" rownum "に" BLANKS "を付けてください。したがって、正しい数の行が得られ、元の値がある場所が出力されます。

+0

ソリューションと説明をありがとう!あなたは天才です! –

0

私はこれを試してみてください、あなたの出力で少し混乱しています:

更新

DECLARE @table TABLE 
    (
     row INT IDENTITY(1, 1) , 
     id1 INT , 
     id2 INT , 
     ch CHAR(1) NOT NULL , 
     val INT 
    ); 

DECLARE @Sequence TABLE (ch3 CHAR(1) NOT NULL); 


INSERT INTO @Sequence 
VALUES ('A'); 
INSERT INTO @Sequence 
VALUES ('B'); 
INSERT INTO @Sequence 
VALUES ('C'); 
INSERT INTO @Sequence 
VALUES ('D'); 

INSERT INTO @table 
VALUES (1112, 121, 'A', 12); 
INSERT INTO @table 
VALUES (1351, 121, 'A', 13); 
INSERT INTO @table 
VALUES (1411, 121, 'B', 81); 
INSERT INTO @table 
VALUES (1312, 7, 'C', 107); 
INSERT INTO @table 
VALUES (1401, 2, 'A', 107); 
INSERT INTO @table 
VALUES (1454, 2, 'D', 107); 
INSERT INTO @table 
VALUES (1257, 6, 'A', 1); 
INSERT INTO @table 
VALUES (1269, 6, 'B', 12); 
INSERT INTO @table 
VALUES (1335, 6, 'C', 12); 
INSERT INTO @table 
VALUES (1341, 6, 'D', 5); 
INSERT INTO @table 
VALUES (1380, 6, 'A', 3); 




SELECT r.id1 , 
     fin.id2 , 
     ch3 , 
     r.val 
FROM (SELECT * 
      FROM  (SELECT CASE WHEN r.chd - l.chd = 1 THEN 0 
            ELSE 1 
           END [gap in sq] , 
           l.* 
         FROM  (SELECT id2 , 
              ASCII(ch) chd , 
              ch , 
              val , 
              id1 , 
              row 
            FROM  @table 
           ) AS l 
           LEFT JOIN (SELECT id2 , 
                ASCII(ch) chd , 
                row 
              FROM @table 
             ) AS r ON l.row = r.row - 1 
        ) AS temp , 
        @Sequence s 
      WHERE  temp.[gap in sq] = 1 
        OR (temp.[gap in sq] = 0 
         AND s.ch3 = temp.ch 
         ) 
     ) AS fin 
     LEFT JOIN @table r ON r.id2 = fin.id2 
           AND r.id1 = fin.id1 
           AND r.ch = fin.ch3 
+0

ありがとう、たくさん!しかし、1351と1411は同じ順序です。だから、1411は、行6で行1351の直後に行かなければならない。 –

0

あなたのテーブル内の余分な列を追加するために管理することができれば、それは[ID2]から一部であるかを定義します同じシーケンスが、あなたはこれを試すことができます。

declare @table table 
(
    id1 int, 
    id2 int, 
    ch char(1) not null, 
    val int, 
    category int -- extra column 
) 

insert into @table values (1112, 121, 'A', 12, 1) 
insert into @table values (1351, 121, 'A', 13, 2) 
insert into @table values (1411, 121, 'B', 81, 2) 
insert into @table values (1312, 7, 'C', 107, 3) 
insert into @table values (1401, 2, 'A', 107, 4) 
insert into @table values (1454, 2, 'D', 107, 4) 
insert into @table values (1257, 6, 'A', 1, 5) 
insert into @table values (1269, 6, 'B', 12, 5) 
insert into @table values (1335, 6, 'C', 12, 5) 
insert into @table values (1341, 6, 'D', 5, 5) 
insert into @table values (1380, 6, 'A', 3, 5) 


DECLARE @sequence table (seq varchar(1)) 
INSERT INTO @sequence values ('A'), ('B'), ('C'), ('D') 


SELECT b.id1, a.id2, a.seq, b.val, a.category 
INTO #T1 
FROM (
    SELECT * 
    FROM @table 
    CROSS JOIN @sequence 
) A 
LEFT JOIN (
    SELECT * FROM @table 
) B 
    ON 1=1 
    AND a.id1 = b.id1 
    AND a.id2 = b.id2 
    AND a.seq = b.ch 
    AND a.val = b.val 


;WITH rem_duplicates AS (
    SELECT *, dup = ROW_NUMBER() OVER (PARTITION by id2, seq, category ORDER BY id1 DESC) 
    FROM #T1 
) DELETE FROM rem_duplicates WHERE dup > 1 


SELECT * FROM #T1 ORDER BY id2 DESC, category ASC, seq ASC 

DROP TABLE #T1 
+0

入力のために感謝、Valerica !.私は、余分な列の定義は、私は反復を回避することができない点だと思います。 –

関連する問題