1

我有一个表格,其中包含测试对具有不同合意性的不同样本执行的一些数据(P1 优于 S1,S1 优于 S3,S3 优于 S2),有时这些测试中的任何一个都可以重复。如果测试失败,则必须有人重新进行测试。

我希望我的查询仅显示最佳样本(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;
4

2 回答 2

3

为此,您可以在子查询中使用row_number() 。

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

您可以在SE-Data上测试查询

说明:
row_number将从中枚举您的行1。该partition by子句控制何时重新开始编号,1并且该order by子句指定编号的顺序。上面使用的over()子句将为您提供您感兴趣row_number()1行。不可能row_number()在查询的 where 子句中使用,因此您必须使用派生表才能根据结果过滤行row_number()

于 2012-04-13T02:55:28.863 回答
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;

它产生与您的示例相同的结果,但没有太多表变量。它也应该比表变量更有效。

这是我的博客的链接,其中包含几个公共表表达式的示例。 http://stevestedman.com/category/classes/cte/

希望这可以帮助。如果您有任何问题,请告诉我。

于 2012-04-13T02:30:29.120 回答