SQL根据共享列有条件地选择一行或两行
我有尝试通过测试的设备。当他们这样做时,我会在设备的数据库中插入一个insert、test、pass或fail以及一个时间戳。我想要的是选择所有通过并失败,但如果已经通过,我不希望失败。如果一次测试多次失败,但没有通过,我只想要最近的一次失败 两个例子。该表共有4行: 设备测试通过时间戳SQL根据共享列有条件地选择一行或两行,sql,sql-server,Sql,Sql Server,我有尝试通过测试的设备。当他们这样做时,我会在设备的数据库中插入一个insert、test、pass或fail以及一个时间戳。我想要的是选择所有通过并失败,但如果已经通过,我不希望失败。如果一次测试多次失败,但没有通过,我只想要最近的一次失败 两个例子。该表共有4行: 设备测试通过时间戳 当它通过时,我只想选择X,我不想失败,因为它现在已经通过了。对于Y,我想要最近的失败。我希望能朝着正确的方向轻推一下。这是一个带有扭曲的优先级查询,可以使用窗口函数或union all实现。让我们来看第二种方法
当它通过时,我只想选择X,我不想失败,因为它现在已经通过了。对于Y,我想要最近的失败。我希望能朝着正确的方向轻推一下。这是一个带有扭曲的优先级查询,可以使用窗口函数或union all实现。让我们来看第二种方法:
select t.*
from t
where t.pass = 1
union all
(select top (1) with ties t.*
from t
where t.pass = 0 and
not exists (select 1 from t t2 where t2.device = t.device and t2.test = t.test and t2.pass = 1)
order by device, test, row_number() over (order by timestamp desc)
)
或者,更简单地说:
select t.*
from (select t.*,
rank() over (partition by by device, test
order by pass desc,
(case when pass = 0 then timestamp end) desc
) as seqnum
from t
) t
where seqnum = 1;
排名的目的是,所有通行证都是第一位的,如果存在,排名值为1。如果没有,则只有最近一次失败的排名为1。联合所有方法的一种变体,使用CTE,通过假定合理的数据集大小的单独分组和过滤来提高可读性
;with LatestPassingTests as
(
select
Device,
Test,
Pass,
max([Timestamp]) as 'Timestamp'
from t
where Pass = 1
group by Device, Test, Pass
),
DeduplicatedTestResults
as
(
select
Device,
Test,
Pass,
[Timestamp]
from LatestPassingTests
union all
select
t.Device,
t.Test,
t.Pass,
max(t.[Timestamp]) as 'Timestamp'
from @tempstuff as t
left outer join LatestPassingTests as p on (t.Device = p.Device)
where p.Device is null
group by t.Device, t.Test, t.Pass
)
select
Device,
Test,
Pass,
[Timestamp]
from DeduplicatedTestResults
如果在同一设备和测试中通过测试后不存在失败的可能性,只需使用一个简单的内部查询,最大时间为:
select Device, Test, Pass, TimeStamp from table
join (
select Device, Test, max(Timstamp) as TimeStamp from table group by 1,2 ) t1
on t1.Device=table.Device and t1.Test=table.Test and t1.TimeStamp =table.TimeStamp
如果在同一设备和测试中通过后可能失败,并且您只需要通过,则需要2个内部连接:
select Device, Test, Pass, TimeStamp from table join (
select Device, Test, Pass, max(TimeStamp) as TimeStamp from table
join (
select Device, Test, max(Pass) as Pass from table group by 1,2 ) t1
on t1.Device=table.Device and t1.Test=table.Test and t1.Pass =table.Pass
group by 1,2,3 ) t2
on t2.Device=table.Device and t2.Test=table.Test and t2.Pass =table.Pass and t2.TimeStamp =table.TimeStamp
到目前为止你尝试了什么?@mucio是一个完全独立的联合,带有一个where子句,不能引用我的表别名。一堆不起作用的东西。这就是union all,第二个select是否应该别名为t2?在从t2中选择1时,我得到t是无效对象。在SQL server中。试图用交叉连接替换。@ScottClark。除了拼写错误之外,这个查询是按照我的意愿编写的。这对我帮助很大。对秩函数的一个很好的介绍。非常感谢。
select Device, Test, Pass, TimeStamp from table join (
select Device, Test, Pass, max(TimeStamp) as TimeStamp from table
join (
select Device, Test, max(Pass) as Pass from table group by 1,2 ) t1
on t1.Device=table.Device and t1.Test=table.Test and t1.Pass =table.Pass
group by 1,2,3 ) t2
on t2.Device=table.Device and t2.Test=table.Test and t2.Pass =table.Pass and t2.TimeStamp =table.TimeStamp