Converting pounds to kilos in SQL - sql

I am trying to pull data from a table with the filter weight < 25 kgs , but my table has weight in pounds, I tried using below sql can some one please tell me is this the right way to do it or is there any other way .
select * from dbo.abc
where (round((WEIGHT * 0.453592 ),0) < 25)

Your solution would work, but it's not sargaeble. A better solution would be to convert your 25kgs to lbs. That way, if you have an index on your WEIGHT column, the query analyzer could make use of it.
One additional note: Why round to 0 decimal places? You'll lose accuracy that way. Unless you have some requirement to do so, I'd drop the rounding. It's unnecessary overhead.

As other people mentioned, you don't want to convert weight as it will cause SQL Server not to use your index. So try this instead:
SELECT *
FROM dbo.acb
WHERE WEIGHT < ROUND(25/.453592,4)

Related

How to query column with letters on SQL?

I'm new to this.
I have a column: (chocolate_weight) On the table : (Chocolate) which has g at the end of every number, so 30x , 2x5g,10g etc.
I want to remove the letter at the end and then query it to show any that weigh greater than 35.
So far I have done
Select *
From Chocolate
Where chocolate_weight IN
(SELECT
REPLACE(chocolote_weight,'x','') From Chocolate) > 35
It is coming back with 0 , even though there are many that weigh more than 35.
Any help is appreciated
Thanks
If 'g' is always the suffix then your current query is along the right lines, but you don't need the IN you can do the replace in the where clause:
SELECT *
FROM Chocolate
WHERE CAST(REPLACE(chocolate_weight,'g','') AS DECIMAL(10, 2)) > 35;
N.B. This works in both the tagged DBMS SQL-Server and MySQL
This will fail (although only silently in MySQL) if you have anything that contains units other than grams though, so what I would strongly suggest is that you fix your design if it is not too late, store the weight as an numeric type and lose the 'g' completely if you only ever store in grams. If you use multiple different units then you may wish to standardise this so all are as grams, or alternatively store the two things in separate columns, one as a decimal/int for the numeric value and a separate column for the weight, e.g.
Weight
Unit
10
g
150
g
1000
lb
The issue you will have here though is that you will have start doing conversions in your queries to ensure you get all results. It is easier to do the conversion once when the data is saved and use a standard measure for all records.

How to limit the character amount you are selecting from

I'm trying to average a field and it's very simple to do but there are some problems with some values. There are values I know are way too big and I was hoping to exclude them by the number of characters (I would probably put 4 characters max).
I'm unfamiliar with a sql clause that could execute this. If there is one that would be great.
select avg(convert(float,duration)) as averageduration
from AsteriskCalls where ISNUMERIC(duration) = 1
I expect the output to be around 500-1000 but it comes up as an 8 digit number.
That is easy enough:
select avg(convert(float,duration)) as averageduration
from AsteriskCalls
where ISNUMERIC(duration) = 1 and length(duration) <= 4;
This will not necessarily work, of course, because you could have '1E30', which would be a pretty big number. And it would miss '0.001', which is a pretty small number.
The more accurate method uses try_convert():
select avg(try_convert(float, duration)) as averageduration
from AsteriskCalls
where try_convert(float, duration) <= 1000.0
And that should probably really be:
where abs(try_convert(float, duration)) <= 1000.0

SQL round off issue

Consider these values which are of type MONEY (sample values and these can change)
select 4796.529 + 1585.0414 + 350.9863 + 223.3549 + 127.6314+479.6529 + 158.5041
for some reason I need to round each value to a scale of 3 like this
select round(4796.529,3)+ round(1585.0414,3)+ round(350.9863,3)+ round(223.3549,3)+ round(127.6314,3)+ round(479.6529,3)+ round(158.5041,3)
but when I take the sum they shows a very minor variation. first line of code returns 7721.7000. and the second one 7721.6990. But this variation in not acceptable. What is the best way to solve this ?
As Whencesoever said, your problem is mathmatical one, not a programming error.
12.5 + 11.6 = 24.1
ROUND(12.5) + ROUND(11.6) = 25
ROUND(12.5 + 11.6) = 24
I'd talk with the business and figure out where they want the rounding applied.
Also, as a side note, MONEY is a terrible datatype. If you can, you may want to consider switching to a DECIMAL. See Should you choose the MONEY or DECIMAL(x,y) datatypes in SQL Server?
When you round numbers before you sum them you will get a different result than if you round numbers after you have summed them. Simple as that. There is no way to solve this.

SQL Server Floating Point in WHERE clause

I'm trying to query a database, I need to get a list of customers where their weight is equal to 60.5. The problem is that 60.5 is a real I've never query a database with a real in a where clause before.
I've tried this:
SELECT Name FROM Customers WHERE Weight=60.5
SELECT Name FROM Customers WHERE Weight=cast(60.5 as real)
SELECT Name FROM Customers WHERE Weight=cast(60.5 as decimal)
SELECT Name FROM Customers WHERE Weight=convert(real,'60.5')
SELECT Name FROM Customers WHERE Weight=convert(decimal,'60.5')
These queries return 0 values but in the Customers table their are 10 rows with Weight=60.5
Your problem is that floating point numbers are inaccurate by definition. Comparing what seems to be 60.5 to a literal 60.5 might not work as you've noticed.
A typical solution is to measure the difference between 2 values, and if it's smaller then some predefined epsilon, consider them equal:
SELECT Name FROM Customers WHERE ABS(Weight-60.5) < 0.001
For better performance, you should actually use:
SELECT Name FROM Customers WHERE Weight BETWEEN 64.999 AND 65.001
If you need equality comparison, you should change the type of the column to DECIMAL. Decimal numbers are stored and compared exactly, while real and float numbers are approximations.
#Amit's answer will work, but it will perform quite poorly in comparison to my approach. ABS(Weight-60.5) < 0.001 is unable to use index seeks. But if you convert the column to DECIMAL, then Weight=60.5 will perform well and use index seeks.

SQL Server LIKE for Integer

I have a column which is integer and I want to search all numbers starting with 1500.
I know I could use something like left(accountid, 4)= 1500.
But is that an optimum solution or is there a better approach?
I am using SQL Server 2005.
LEFT(CONVERT(varchar, accountid),4)="1500"
An INT is an INT is an INT - it's just a numeric value. An INT doesn't "look" like some string value..... if you want to compare with LIKE, you need a string - you need to convert your INT to a string to be able to do that.
If you need to search and compare against that string representation of your INT a lot, I would recommend making it a computed, persisted column on your table:
ALTER TABLE dbo.YourTable
ADD IntString AS LEFT(CAST(YourInt AS VARCHAR(20)), 4) PERSISTED
That way, you get a new column that has a value inside it, that value is always up to date, it's a persisted column, you can index it if needed - you get all the benefits of comparing your "int" with the LIKE operator :-)
If you're willing to trade storage space for performance speed, I would add a persisted, computed column to the table containing the string version of the integer, index appropriately, and use that column for searching.
Assuming you know the minimum and maximum values for your column, you can do this:
select
stuff
from
table
where
(number = 1500)
or (number >= 15000 and number <= 15009)
or (number >= 150000 and number <= 150099)
or (number >= 1500000 and number <= 1500999)
or (number >= 15000000 and number <= 15009999)
-- add however many statements you need.
Or if you don't know the minimums and maximums, you could do this:
...
where
(number - 1500*POWER(10, FLOOR(LOG10(number) - 3)))
< (POWER(10, FLOOR(LOG10(number) - 3)))
If you want to go even further, why not create like a super category for accounts and that would eliminate the need to perform LEFT() on a converted varchar from an integer. To clarify, if you know all accounts beginning with id 1500 are say, accounts related to sales, you could have a super category of 1500 for all of them. This certainly only applies if this hierarchical relationship exists =).
It all depends on the volume of data. If you are talking about millions of records then using left with convert will not be quick. The best possible option would be have a computed column which stores the first four digits and you doing a search from it directly would be the fastest. But every insert or update would take a little more time. So it all depends on how many rows you are dealing with.
HTH
select columnname from dbo.TB
where CONVERT(varchar(20), columnname ) like '15'+'%'