我有以下表格 - 简化了很多
Table - Tests
Test
A
B
C
D
E
F
G
H
Table - TestHistory
Test Result Version
A Pass 1
A Fail 2
B Pass 2
C Fail 1
C Pass 2
D Fail 1
D Fail 2
E Fail 1
我想获取上次运行时失败(或任何状态)的测试列表。但是,也是它的版本。
所以,在上面的例子中,我想要返回:
A Fail 2
D Fail 2
E Fail 1
我尝试了几种方法
select Test, LastResult = IsNull((Select Top 1 Result From TestHistory Where Test = Tests.Test order by Version desc), 'NOT_RUN')
from Tests
这样做,是给我一个所有测试的列表,然后我必须经历并踢出我不想要的行(即不是失败)。这也没有给我它运行的版本。
我也试过这个:
select Version, TH.Test, Result
from TestHistory as TH inner join Tests as T on TH.Test = T.Test
where Result = 'Fail'
但是,我得到的行如下:
Test Result Version
C Fail 1
我不想要那些因为它不是最后结果。
如何在没有大量数据操作(或者更糟糕的是,更多数据库读取)的情况下限制它以准确地提供我所需要的内容?任何帮助,将不胜感激。谢谢!
答案 0 :(得分:2)
我无法对此进行语法检查,但它应该是关闭的:
SELECT
th.Test,
th.Result,
th.Version
FROM
TestHistory th
INNER JOIN
(
SELECT
MAX(Version) as MaxVersion,
Test
FROM
TestHistory
GROUP BY
Test
) sub ON sub.MaxVersion = th.Version AND sub.Test = th.Test
WHERE
th.result = 'Fail'
说明:首先,在子查询中,您将获得测试的最大版本。然后使用连接将外部查询限制为仅返回与子查询的测试/版本匹配的结果。
编辑:忘记了WHERE子句 - 似乎你只想要最近结果失败的行。
根据评论中的问题进行修改:
这应该会给你最近的失败,以及从未运行过的测试。请注意,这将过滤掉已运行但从未失败的测试(您的数据没有任何这些)。为了时间的缘故,我基于原始查询,但我猜有更优雅的方式:
SELECT
t.Test,
outerSub.Result,
outerSub.Version
FROM
Test t
LEFT JOIN
(SELECT
th.Test,
th.Result,
th.Version
FROM
TestHistory th
INNER JOIN
(
SELECT
MAX(Version) as MaxVersion,
Test
FROM
TestHistory
GROUP BY
Test
) sub ON sub.MaxVersion = th.Version AND sub.Test = th.Test
) outerSub on outerSub.Test = t.Test
WHERE
outerSub.result = 'Fail' OR outerSub.Test IS NULL
答案 1 :(得分:2)
可以在上述解决方案中添加小的修正。 如果您需要在测试订单中接收结果,可以按如下方式转换查询:
SELECT src.Test, src.Result, src.Version
FROM
(
SELECT th.Version, th.Test, th.Result,
ROW_NUMBER() over(partition by th.Test order by th.Version desc) as RowNum
FROM dbo.TestHistory as th
) src
WHERE src.RowNum = 1 and src.Result = 'Fail'
order by src.Test;
其中,查询将以所需列的顺序返回该集。
答案 2 :(得分:1)
怎么样:
select th.* from testHistory th
where th.result = 'fail' -- this part, according to you, being optional
and th.version =
(select max(t.version) from testhistory t
where t.test = th.test);