用于查找彼此接近的值的 SQL 语句

Posted

技术标签:

【中文标题】用于查找彼此接近的值的 SQL 语句【英文标题】:SQL statement to find values close to each other 【发布时间】:2015-06-05 19:28:54 【问题描述】:

我正在努力定义 SQL 以查找在统计上彼此接近的值列表。例如,假设我们有一张价格表,我想获取所有价格相差在 0.25 美元以内的价格。

价格: 1.00 1.25 2.00 4.00 4.50 4.75 5.00

对于上面的示例,这应该返回 1.00、1.25、4.50、4.75 和 5.00,因为它们在列表中另一个值的 0.25 范围内。

我不想获取原始列表,然后在代码中对其进行处理。 SQL Server 完成这项工作会更有效率。这可能吗?

【问题讨论】:

SQL Server 的哪个版本?这可能会影响投注答案。此外,对于这种处理,SQL 不一定比加载列表和处理更有效。 这适用于 SQL Server v11.0。 【参考方案1】:

尝试将表与自身连接:

declare @Values table (value float)
insert into @Values values (1),(1.25),(2),(4),(4.5),(4.75),(5)

select distinct A.Value
from @values A
inner join @Values B
    on abs(A.value - B.Value) <= 0.25
    and A.Value <> B.Value

SQL Fiddle

或者在另一种方法中,使用CROSS APPLY

SELECT DISTINCT CASE WHEN N.n=1 THEN A.Value ELSE ant END
FROM @Values A
cross apply (select max(value) from @Values where Value < A.Value) B(ant)
CROSS APPLY(SELECT 1 UNION SELECT 2)N(n)
where abs(A.value - ant) <= 0.25

SQL Fiddle

而且,如果您使用的是 SQL Server 2012+,则可以使用 LEAD 函数:

SELECT DISTINCT CASE WHEN N.n=1 THEN A.Value ELSE ant END
FROM (
    SELECT Value, 
        LEAD(Value, 1,0) OVER (ORDER BY Value) AS Ant
    FROM @Values
) A
CROSS APPLY(SELECT 1 UNION SELECT 2)N(n)
where abs(Ant - Value) <= 0.25

SQL Fiddle

【讨论】:

谢谢尼扎姆。这似乎很有希望,但是,它将列表限制为不同的值。就我而言,我需要所有彼此接近的值。 您可以使用子查询,例如SELECT * FROM @VALUES WHERE VALUE IN ( --- one of the suggested solutions --- )。请看sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/482。【参考方案2】:

我可能会使用相关子查询:

DECLARE @tbl TABLE (val DECIMAL (9,2))
INSERT INTO @tbl VALUES (1),(1.25),(2),(4),(4.5),(4.75),(5)

SELECT * 
  FROM @tbl a 
 WHERE EXISTS(SELECT 1 
                FROM @tbl b 
               WHERE     b.val <> a.val 
                     AND b.val BETWEEN a.val-.25 AND a.val+.25)

您也可以在其中使用 ABS,这可能更简洁,但可能不会影响性能:

SELECT * 
  FROM @tbl a 
 WHERE EXISTS(SELECT 1 
                FROM @tbl b 
               WHERE     b.val <> a.val 
                     AND ABS(b.val - a.val) <= .25)

编辑:我从 Float 切换到 Decimal,因为这是 SQL Server 中“更好”的类型。

【讨论】:

谢谢卡尔。这正是我一直在寻找的。当我在表中有多个值时,例如1, 1.25, 1.25, 2, 4, 4.5, 4.75, 5,结果是 1, 1.25, 1.25, 4.5, 4.75, 5。完美!【参考方案3】:

试试这个;

DECLARE @TBL TABLE (Nums float)

insert into @TBL values (1),(1.25),(2),(4),(4.5),(4.75),(5);

WITH CTE AS(
Select  t1.Nums as T1,t2.Nums as T2 From @TBL t1
CROSS JOIN @TBL t2)
Select  distinct ct.T1 From CTE ct
where abs(ct.T1 - ct.T2) = 0.25
order by ct.T1

【讨论】:

以上是关于用于查找彼此接近的值的 SQL 语句的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 查找插入特定值的语句

sql语句更新字段里面的值,比方说 我要去掉某一列里面所有值的最后的一个字母(有空值)

带有在子查询中生成的值的 Oracle SQL 更新语句

SQL语句:统计指定字段,等于不同值的条数

SQL语句 一个表的值与另一个表的字段一致,怎么把两一个表的值作为条件,限定查询的字段

oracle语句,我想查询A表中的a字段下的值不等于B表中b的值的数据,