2015-08-31 48 views

回答

0

在内部查询中,您可以选择列的最大长度并在外部查询中将其消除,然后执行max,以便获得该列中的第二大长度。

select max(val) as secondlargest 
from t join 
(
SELECT max(len(val)) as lf1 
FROM t 
) x 
on len(t.val) < x.lf1 

如果您需要所有长度第二大的值,最好使用cte s。 SQL Fiddle

with top2 as (
select top 2 len(val) as lf1 
from t 
order by len(val) desc 
) , 
scnd as 
(select min(lf1) as snd from top2) 
select val 
from t join scnd 
on len(t.val) = scnd.snd 
+0

vkp,max(val)不处理长度。它应该是max(len(val))不是吗? – ElenaDBA

+0

@ ElenaDBA ..在第一个查询中,第二个最大长度只能得到一个“val”。但是,使用'cte'的第二个查询将为您提供第二个最大长度的所有值。 –

3

的SQL Server 2012+支持OFFSET/FETCH

select len(f1) 
from table1 
group by len(f1) 
order by len(f1) desc 
offset 1 
fetch first 1 row only; 

在早期版本也有不同的方法。这里是一个:

with ml as (
     select len(f1) as lenf 
     from table1 
     group by len(f1) 
    ) 
select max(lenf) 
from ml 
where lenf < (select max(lenf) from ml); 
+0

,它给了我“错误的语法靠近'抵消'” – ElenaDBA

+0

然后推测你正在使用早期版本的SQL Server。 –

+0

我正在使用Azure SQL并通过Management Studio 2014 – ElenaDBA

0

如果你只需要第二个:

SELECT MAX(Field1) FROM Table1 
WHERE Field1 NOT IN (SELECT MAX(Field1) FROM Table1) 

请注意,这是唯一正确的,当两个极大值是不一样的。如果他们是,第二个答案仍然会被选中。例如:

1: 500 points 
2: 500 points 
3: 410 points 

2将仍然被选中,但它是有争议的,你需要哪个答案。

1

窗口功能通常是最有效的方法来做到这一点,它们最终是灵活的,以适应不同的要求。下面是一个例子(Azure上的SQL数据库进行测试):

select f1, lenf, lenf_dense_rank 
from (
     SELECT 
      f1, 
      lenf=len(f1), 
      lenf_dense_rank=dense_rank() over (order by len(f1) desc) 
     FROM table1 
) x 
where lenf_dense_rank = 2 

此外,根据您的需求,您可能需要使用rank()dense_rank(),但窗口功能仍然使用了这样的情况的技术。强烈建议查找它们并更多地了解它们 - 应该比目前更频繁地使用它们。

+0

顺便说一句,通过说“通常更高效”,我的意思是你正在做1次全表扫描(或索引扫描),而自连接,并且在同一个表上使用max和子查询,需要至少2相同类型的扫描 - 数据库管理系统完成的相关工作量不应忽视!使用OFFSET/FETCH组合确实有效,但窗口函数可以做得更多,现在得到了广泛的支持,所以我必须尽可能地推荐它们。 – SlimsGhost

相关问题