|
Try something like this:
DECLARE @Input int
SET @Input = 30
SELECT TOP 1 Col1 FROM Table1
WHERE Col1 = (SELECT MIN(ABS(Col1-@Input))+@Input FROM Table1)
OR Col1 = (SELECT @Input-MIN(ABS(Col1-@Input)) FROM Table1)
You may need to modify this query.
|
|
|
|
|
you can use the least-square approach, provided your numbers won't overflow when squared.
Example:
SELECT * FROM news1 ORDER BY (news_id-10)*(news_id-10)
would order the news items according to their distance of news_id value 10.
Then optionally pick the first one, or first few, with whatever your SQL environment needs for doing that
(often "TOP 1").
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Awesome answer. Thanks for teaching me something new.
|
|
|
|
|
Better yet, this query works too:
SELECT * FROM news1 ORDER BY ABS(news_id-10)
|
|
|
|
|
of course it does, however using squares is a common technique to optimize a "cost function", say when you need to find a best match for several parameters, you do:
"... ORDERBY (var1-goal1)*(var1-goal1)+(var2-goal2)*(var2-goal2)...+(varN-goalN)*(varN-goalN)"
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
I believe the above will order the items by the value of news_id-10, not by their distance from the target value of 30. To do that, you would have to change the ORDER BY clause to
((news_id-10 * new_id-10) - (target_value * target_value)).
It might be easier still to use
ABS(ABS(news_id-10) - ABS(target_value))
though using the function ABS() may slow execution somewhat.
I've been trying to figure out a way to use MIN(ABS(news_id-10) - ABS(target_value)) in a way that will return a record instead of a single value, but I lack the knowledge for that (for now). That would give him the desired information in one step.
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
|
|
|
|
|
Hi Roger,
I don't know what you are trying with all those ABS functions, they don't make sense to me.
My point is: to order items according to their distance from a target or goal, you either use a single ABS (useful only for one criterium, one goal), or a least-square approach (where you calculate a formula involving squaring deviations as I indicated before). My example with news_id (and target 10) wasn't an exact match for the OP, it was the code that I tested for something of mine.
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
I thought the ABS function might be a shortcut, in that it accomplishes the same thing as squaring when you want only the distance between two values, regardless of which is smaller. My main consideration was that the example you gave did not return a distance from the target of 30, only reorders the table. Now that I reread your response, I see that the value I was reading as a single variable (news_id-10) is actually (new_id - 10). That's what I get for reading this stuff late at night after a long day at work, wiring sewer plant pump motors in a frigid dust storm. My bad.
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
|
|
|
|
|
NP
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
This will work gracefully
declare @t table(num int)
insert into @t
select 12 union all select 43
union all select 31 union all select 35
declare @inputNum int
set @inputNum = 30
select num as [Closest Number] from(
select DENSE_RANK() over(order by abs(num - @inputNum)) [rank]
,num from @t
)X
where [rank] = 1
Output:
Closest Number
31
Note: Try with
Input Output
100 43
-1 12
39 43 & 35
(which is correct only because the difference is 4 for both the case). Henceforth I have used Dense_Rank()
Hope this helps
Niladri Biswas
modified on Monday, November 23, 2009 9:37 AM
|
|
|
|
|
thanks you so much Niladri Diswas....
VB.Net
|
|
|
|
|
Here is a better answer:
DECLARE @i int
SET @i = 30
SELECT TOP 1 Col1 FROM Table1 ORDER BY ABS(Col1-@i)
|
|
|
|
|
Hi,
Just 1 question to ask?
If the input is 39 what be the output? Is it 43 or 35 or both?
If the answer is the last one, then how
Shameel wrote: TOP 1 Col1
will help?
Niladri Biswas
|
|
|
|
|
If you remove the 'TOP 1' clause, you will see that the query returns both values. Adding TOP clause arbitrarily returns the first match.
|
|
|
|
|
Dear All
Thanks for you help.
Now i can get that task ready.
Best regards,
VB.Net
|
|
|
|
|
I am sure I have to explain this with more details..
People names in Arabic have more than one way to spell it.. for example, Hassan can be spelled with double or single S & Mohammad can be spelled (Mohammad) or (Mohd) or (Moh’d) or (Mohammed), etc… & my name can be spelled the way I spell it (Jassim) or (Jasim) or (Jassem) or (Jasem).. can you believe that?!!!
Now, what if I have the following name in my customers table in the full_name record
JASSIM MOHD HASSAN
And the user entered the following name:
JASIM MOHD HASAN
Or:
JASSIM MOHAMMAD HASSAN
Or any other different spelling way..
How can I search for similar names in the full_name records and alert the user for possible existing names?
|
|
|
|
|
This is not a perfect solution, but hopefully it might help.
If you separate out first, middle, and last name, then you might be able to look at sum of two instr(.) calls being greater than 0 when you search for the first few and last few characters. Given the names that match based on first and last name, then eliminate only based on middle as it might be left out.
You also might call a user defined function to count the # of matching characters (properly ordered) in each name on your smaller result set.
|
|
|
|
|
SOUNDEX is the standard way of handling phonetic searches in Sql Server but it can return lots of false matches.
|
|
|
|
|
Hi,
IMO you can solve such problems by using a "canonical form"; for each possible value, the canonical value should be defined somehow, in your example it could be the alphabetically first of all equivalent names, so in your Jassim example it would be Jasem. So you store the original value (Jassim) and the canonical value (Jasem); when a search is launched for say Jasim, you look up or compute its canonical value (again Jasem) and launch a search for that canonical value.
Again in your example, the canonical form would probably be defined by a database table, which also means you can store its unique ID rather than its string value.
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Hi,
I agree with Mr. Russel that though soundex will help in such situations but it will cause problems on the other hand by delivering extra results.
I suggest better use Metaphone(which was first described by Lawrence Philips in the December 1990 edition of Computer Language magazine) for serving your purpose
Look here for SQL Version
Metaphone (Simple and Double)
and here for Oracle Version(You will find the code in Listing A)
Consider algorithms other than Soundex
Hope this helps
Niladri Biswas
|
|
|
|
|
SOUNDEX function is the simplest way to start. But it matches only based on phonetic similarities. For example, 'Mohammed' and 'Mohamed' will match but not 'Mohd', since it has a completely different pronounciation. You need to write your own function to take care of such cases, probably by storing canonical forms of common names and comparing it with the input.
|
|
|
|
|
As noted by other posters, soundex is the easiest solution although it may not always work quite as expected.
A better "fuzzy matching" algorithm is the Levenstein algorithm which is pretty good, but you would probably have to code up your own solution for that and it might be a challenge to get it to perform over a large database. (Plenty of articles available if you Google for it.)
Or, you could use a full text search engine like Lucene or MS Search Server which might be overkill for you but which do have some nice built-in fuzzy search support. (They are intended for searching documents but you can get adaptors to run them over relational databases as well.)
|
|
|
|
|
Hi All ,
I'm beganer in SQL ,and I'm going to install aplication in the coustomer PC .My boss ask me to install Microsoft SQL Server 2005 Client version in the customer pc.
my qustion is , what is the "Microsoft SQL Server 2005 Client version"? is it the sql native client or not?
form where can i install it ? and how? is it free?
Many thanks,
|
|
|
|
|
Take a look at the information on Microsoft's SQL site[^], where you should be able to find what you need. I am not aware of a "client version" of SQL 2005 so you may need to clarify what it is that you will be running on the client PC. I assume that you already have the SQL Server installed somewhere.
|
|
|
|
|
If the client is to query your database from his own SQL Server, then SQL Server Compact or Express Edition might be needed. See http://www.microsoft.com/sqlserver/2008/en/us/editions.aspx
If you use non-generic connection strings in your project (e.g. a different vendor's OLE DB provider for SQL Server 2008) and installed a driver, then you might need to download the appropriate drivers to the client machine.
|
|
|
|