2012-04-13 11 views
1

Ich habe eine Tabelle mit einigen der Daten, die ein Test auf verschiedene Proben, die unterschiedliche wünschenswerte (P1 ist besser als S1 was besser als S3 ist, was besser ist als S2) UND manchmal konnte jeder dieser Tests wiederholt werden. Wenn ein Test fehlschlägt, muss jemand es tun.Wie wähle ich den höchsten Wert einer Spalte und eine der Wiederholungen in einer Tabelle mit t-sql

Ich möchte meine Abfrage nur die beste Probe anzeigen (P1> S1> S3> S2) UND nur die wiederholten Daten (nicht die ursprünglichen Daten).

Die folgende Abfrage funktioniert, aber wie Sie sehen können, ist es ziemlich lang und kompliziert. Ich bin immer noch ein Junior-SQL-Person, also wie kann ich dasselbe mit einer kürzeren/besseren Abfrage erreichen?

Ich versuche, besser SQL zu lernen, also muss ich nicht immer diese Art von Fragen stellen, also Erklärungen, warum Ihre Abfrage besser funktioniert, wäre sehr hilfreich!

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; 

Antwort

3

Sie können dazu row_number() in einer Unterabfrage verwenden.

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 

können Sie testen Sie die Abfrage auf SE-Data

Erläuterung:
row_number Ihre Zeilen aus 1 aufzählen wird. Die partition by Klausel steuert, wenn die Nummerierung wieder von 1 beginnt, und die order by Klausel gibt die Reihenfolge der Nummerierung an. Die over() Klausel, die oben verwendet wird, gibt Ihnen row_number() von 1 für die Zeilen, die Sie interessieren. Es ist nicht möglich, row_number() in der Where-Klausel einer Abfrage zu verwenden, so dass Sie eine abgeleitete Tabelle verwenden müssen, um Ihre Zeilen zu filtern Das Ergebnis von row_number()

+0

Ein gutes Verständnis der Ranking-Funktionen finden Sie hier: http://www.sqllion.com/2010/07/ranking-functions/ – Ferdeen

0

Versuchen Sie, allgemeine Tabellenausdrücke zu verwenden. Sie müssen nicht alle Tabellenvariablen erstellen, es könnte ein wenig sauberer sein. Hier ist ein Beispiel, ich behielt die ursprüngliche Tabellenvariable aus Ihrem Beispiel für die Quelldaten.

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; 

Es produziert die gleichen Ergebnisse wie Ihr Beispiel, ohne so viele Tabellenvariablen. Es sollte auch viel effizienter sein, dass die Tabellenvariablen.

Hier ist ein Link zu meinem Blog mit mehreren Beispielen der Common Table Expressions. http://stevestedman.com/category/classes/cte/

Hoffe das hilft. Lass es mich wissen, wenn du irgendwelche Fragen hast.

+0

Sie könnten wahrscheinlich das gleiche mit Unterabfragen tun, aber das wäre viel mehr ein Durcheinander. –

Verwandte Themen