2012-04-13 7 views
1

私は、テストが異なるサンプルに対して異なるデータを持つテーブルを用意しています(P1はS1よりも優れています) S2よりも優れているS3よりも優れています)、時にはこれらのテストのいずれかを繰り返すことができます。テストが失敗した場合、誰かがそれをやり直さなければなりません。t-sqlを使用してテーブル内の1つのカラムとリピートの最高値を選択するには

クエリには、最良のサンプル(P1> S1> S3> S2)と繰り返しデータのみが表示されます(元のデータではありません)。

次のクエリは機能しますが、わかるように、時間がかかり複雑です。私はまだ未熟なSQLの人ですから、より短く/より良いクエリで同じことをどうやって達成できますか?

私はより良いSQLを学ぼうとしているので、これらのタイプの質問を常に行う必要はありませんので、クエリがうまく機能する理由の説明が非常に役立ちます。

DECLARE @TempTable TABLE (Sample_ID varchar(10), TestRepeat int, TestResult varchar(1)) 
    -- In the end, ONLY the samples with Y should be displayed 
    INSERT INTO @TempTable VALUES('61-0001-P1', 0, 'R') -- 1 Y 
    INSERT INTO @TempTable VALUES('61-0002-P1', 0, 'R') -- 2 Y 
    INSERT INTO @TempTable VALUES('61-0003-S1', 0, 'S') -- 3 Y 
    INSERT INTO @TempTable VALUES('61-0004-S1', 0, 'R') -- 4 Y 
    INSERT INTO @TempTable VALUES('61-0005-P1', 0, 'I') -- 5 
    INSERT INTO @TempTable VALUES('61-0005-P1', 1, 'S') -- 6 Y 
    INSERT INTO @TempTable VALUES('61-0006-P1', 0, 'S') -- 7 Y 
    INSERT INTO @TempTable VALUES('61-0006-S3', 0, 'R') -- 8 
    INSERT INTO @TempTable VALUES('61-0007-P1', 0, 'S') -- 9 Y 
    INSERT INTO @TempTable VALUES('61-0008-S3', 0, 'I') -- 10 
    INSERT INTO @TempTable VALUES('61-0008-S3', 1, 'R') -- 11 Y 
    INSERT INTO @TempTable VALUES('61-0009-P1', 0, 'R') -- 12 Y 
    INSERT INTO @TempTable VALUES('61-0009-S1', 0, 'S') -- 13 
    INSERT INTO @TempTable VALUES('61-0010-P1', 0, 'S') -- 14 Y 
    INSERT INTO @TempTable VALUES('61-0011-S3', 0, 'S') -- 15 Y 

    DECLARE @TempTable1 TABLE (Subject_ID varchar(7), Sample_ID varchar(10), SampleOrder int, TestRepeat int, TestResult varchar(1)) 

    INSERT @TempTable1 
    SELECT LEFT(Sample_ID,7) AS Subject_ID, 
    Sample_ID, 
    SampleOrder = 
     CASE 
     WHEN RIGHT(Sample_ID,2) = 'P1' THEN 4 
     WHEN RIGHT(Sample_ID,2) = 'S1' THEN 3 
     WHEN RIGHT(Sample_ID,2) = 'S3' THEN 2 
     WHEN RIGHT(Sample_ID,2) = 'S2' THEN 1 
     END, 
    TestRepeat, 
    TestResult 
    FROM @TempTable 
    ORDER BY Subject_ID, SampleOrder; 

    --SELECT * FROM @TempTable1; 

    DECLARE @TempTable2 TABLE (Sample_ID varchar(10), TestRepeat int, TestResult varchar(1)) 

    INSERT @TempTable2 SELECT 
    tt1.Sample_ID, 
    tt1.TestRepeat, 
    tt1.TestResult 
    FROM @TempTable1 tt1 
    INNER JOIN (
     SELECT Subject_ID, MAX(SampleOrder) AS Max_SampleOrder 
     FROM @TempTable1 
     GROUP BY Subject_ID) subQ1 
     ON (tt1.Subject_ID=subQ1.Subject_ID AND tt1.SampleOrder=subQ1.Max_SampleOrder) 
    ORDER BY tt1.Sample_ID; 

    SELECT tt2.Sample_ID, 
      tt2.TestRepeat, 
      tt2.TestResult 
    FROM @TempTable2 tt2 
    INNER JOIN (
     SELECT Sample_ID, MAX(TestRepeat) AS Max_TestRepeat 
     FROM @TempTable2 
     GROUP BY Sample_ID) subQ 
     ON (tt2.Sample_ID = subQ.Sample_ID AND tt2.TestRepeat=subq.Max_TestRepeat) 
    ORDER BY tt2.Sample_ID, tt2.TestResult; 

答えて

3

サブクエリでrow_number()を使用できます。あなたはSE-Data

説明にクエリをテストすることができ

select Sample_ID, TestRepeat, TestResult 
from 
    (
    select Sample_ID, TestRepeat, TestResult, 
      row_number() over(partition by left(Sample_ID, 7) 
          order by case right(Sample_ID,2) 
             when 'P1' then 1 
             when 'S1' then 2 
             when 'S3' then 3 
             when 'S2' then 4 
             end, TestRepeat desc) as rn 
    from @TempTable 
) as T 
where rn = 1 
order by Sample_ID 


row_number1からあなたの行を列挙します。 partition by句は、番号付けが1から再び開始され、order by句が番号付けの順序を指定するときに制御されます。上記のover()句では、row_number()1が表示されます。row_number()をクエリのwhere句に使用することはできません。したがって、派生テーブルを使用して行をフィルタリングする必要がありますrow_number()

+0

ランキング機能の詳細については、次のURLを参照してください。http://www.sqllion.com/2010/07/ranking-functions/ – Ferdeen

0

共通テーブル式を使用してください。すべてのテーブル変数を作成する必要はありませんが、少し面倒かもしれません。ここでは例を示します。ソースデータのサンプルから、元のテーブル変数を保持しました。

DECLARE @TempTable TABLE (Sample_ID varchar(10), TestRepeat int, TestResult varchar(1)) 
-- In the end, ONLY the samples with Y should be displayed 
INSERT INTO @TempTable VALUES('61-0001-P1', 0, 'R') -- 1 Y 
INSERT INTO @TempTable VALUES('61-0002-P1', 0, 'R') -- 2 Y 
INSERT INTO @TempTable VALUES('61-0003-S1', 0, 'S') -- 3 Y 
INSERT INTO @TempTable VALUES('61-0004-S1', 0, 'R') -- 4 Y 
INSERT INTO @TempTable VALUES('61-0005-P1', 0, 'I') -- 5 
INSERT INTO @TempTable VALUES('61-0005-P1', 1, 'S') -- 6 Y 
INSERT INTO @TempTable VALUES('61-0006-P1', 0, 'S') -- 7 Y 
INSERT INTO @TempTable VALUES('61-0006-S3', 0, 'R') -- 8 
INSERT INTO @TempTable VALUES('61-0007-P1', 0, 'S') -- 9 Y 
INSERT INTO @TempTable VALUES('61-0008-S3', 0, 'I') -- 10 
INSERT INTO @TempTable VALUES('61-0008-S3', 1, 'R') -- 11 Y 
INSERT INTO @TempTable VALUES('61-0009-P1', 0, 'R') -- 12 Y 
INSERT INTO @TempTable VALUES('61-0009-S1', 0, 'S') -- 13 
INSERT INTO @TempTable VALUES('61-0010-P1', 0, 'S') -- 14 Y 
INSERT INTO @TempTable VALUES('61-0011-S3', 0, 'S') -- 15 Y 


;with CTE1 as 
(
    SELECT LEFT(Sample_ID,7) AS Subject_ID, 
     Sample_ID, 
     SampleOrder = 
     CASE 
      WHEN RIGHT(Sample_ID,2) = 'P1' THEN 4 
      WHEN RIGHT(Sample_ID,2) = 'S1' THEN 3 
      WHEN RIGHT(Sample_ID,2) = 'S3' THEN 2 
      WHEN RIGHT(Sample_ID,2) = 'S2' THEN 1 
     END, 
     TestRepeat, 
     TestResult 
    FROM @TempTable 
), 
CTE2 as 
(
SELECT 
     tt1.Sample_ID, 
     tt1.TestRepeat, 
     tt1.TestResult 
    FROM CTE1 tt1 
    INNER JOIN (
     SELECT Subject_ID, MAX(SampleOrder) AS Max_SampleOrder 
     FROM CTE1 
     GROUP BY Subject_ID) subQ1 
     ON (tt1.Subject_ID=subQ1.Subject_ID AND tt1.SampleOrder=subQ1.Max_SampleOrder) 
    ), 
CTE3 as 
(
    SELECT tt2.Sample_ID, 
      tt2.TestRepeat, 
      tt2.TestResult 
    FROM CTE2 tt2 
    INNER JOIN (
     SELECT Sample_ID, MAX(TestRepeat) AS Max_TestRepeat 
     FROM CTE2 
     GROUP BY Sample_ID) subQ 
     ON (tt2.Sample_ID = subQ.Sample_ID AND tt2.TestRepeat=subq.Max_TestRepeat) 
) 
select * 
from CTE3; 

多くのテーブル変数がなくても、例と同じ結果が得られます。また、テーブル変数よりもはるかに効率的でなければなりません。

ここに、私のブログへのリンクがあります。いくつかのCommon Table Expressionsの例があります。 http://stevestedman.com/category/classes/cte/

これが役に立ちます。ご質問がある場合はお知らせください。

+0

おそらくサブクエリで同じことを行うことはできますが、それははるかに混乱するでしょう。 –

関連する問題