在数据库中查找最接近的数值

我需要find一个select语句,它将返回一个与我的input完全匹配的logging,或者如果找不到完全匹配,则返回最接近的匹配。

这是我迄今为止的select陈述。

SELECT * FROM [myTable] WHERE Name = 'Test' AND Size = 2 AND PType = 'p' ORDER BY Area DESC 

我需要做的是find最接近的“区域”字段,所以如果我的input是1.125和数据库包含2,1.5,1和0.5查询将返回包含1的logging。

我的SQL技能是非常有限的,所以任何帮助将不胜感激。

得到区域和你的input之间的差异,取绝对值,所以总是积极的,然后顺序升序,并采取第一个

 SELECT TOP 1 * FROM [myTable] WHERE Name = 'Test' and Size = 2 and PType = 'p' ORDER BY ABS( Area - @input ) 

可怕的东西,沿着:

 ORDER BY ABS( Area - 1.125 ) ASC LIMIT 1 

也许?

如何根据您的input和[区域]之间的差异进行sorting,例如:

 DECLARE @InputValue DECIMAL(7, 3) SET @InputValue = 1.125 SELECT TOP 1 * FROM [myTable] WHERE Name = 'Test' AND Size = 2 AND PType = 'p' ORDER BY ABS(@InputValue - Area) 
 SELECT * FROM [myTable] WHERE Name = 'Test' AND Size = 2 AND PType = 'p' ORDER BY ABS(Area - 1.125) LIMIT 1 

– MarkusQ

如果有许多行满足NameSizePType列上的相等谓词,则可能需要在查询中的Area列中包含范围谓词。 如果Area列索引,这可以允许有效的基于索引的访问。

以下查询(使用Oracle语法编写)使用UNION ALL一个分支来查找最小Area >=您的目标的logging,而另一个分支查找最大Area <您的目标的logging。 这两个logging之一将是您正在寻找的logging。 然后你可以通过ORDER BY ABS(Area - ?input)来从这两个候选人中挑选出获胜者。 不幸的是,查询是复杂的,因为需要强制执行所需的ROWNUM / ORDER BY优先级的嵌套SELECTS。

 SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM [myTable] WHERE Name = 'Test' AND Size = 2 AND PType = 'p' AND Area >= ?target ORDER BY Area) WHERE ROWNUM < 2 UNION ALL SELECT * FROM (SELECT * FROM [myTable] WHERE Name = 'Test' AND Size = 2 AND PType = 'p' AND Area < ?target ORDER BY Area DESC) WHERE ROWNUM < 2) ORDER BY ABS(Area - ?target)) WHERE rownum < 2 

这个查询的一个好的索引是(Name, Size, PType, Area) ,在这种情况下,预期的查询执行计划将基于两个索引范围扫描,每个索引范围扫描返回一行。

请注意,尽pipeABS()几乎支持所有的东西,但它在技术上并不标准(至less在SQL99中)。 如果由于某种原因必须编写ANSI标准SQL,则必须使用CASE运算符解决该问题:

 SELECT * FROM myTable WHERE Name='Test' AND Size=2 AND PType='p' ORDER BY CASE Area>1.125 WHEN 1 THEN Area-1.125 ELSE 1.125-Area END 

如果使用MySQL

 SELECT * FROM [myTable] ... ORDER BY ABS(Area - SuppliedValue) LIMIT 1 

selectmin [where]> your_target_valueselectmax的地方[field] <your_target_value