SQL Server : aggregate function doesn't work? - sql

I have imported a price list from a csv to my SQL Server database. That has worked fine. But now some weird stuff. Table is named PRICE which includes a column (and some more) Endprice and a total of 761 rows. All datatypes are varchar(50).
SELECT MAX(Endprice)
FROM PRICE
When I want this simple SQL statement to show the highest price in the column, I get a wrong result. I don't know why.
I get 98,39 as a result, but that's definitively wrong, it must be 100,73.
Here you can see a part of the data:
And now the wrong MAX() result:
BUT when I'm using the MIN function I get the highest one!? The min is somewhere at ~50 (not shown in the screenshot part).
`
The resultset of SELECT Endprice FROM PRICE is correct. I am at my wit's end.

This is because your column is a varchar, so it is determining the min or max based on characters. The column should be a decimal or money type, so it sorts by the value of your number (instead of an alphabetic sort like you are getting now).
Alphabetic sort: 9 is more than 1, thus 98.39 is the max.

The reason is because price is a varchar().
Here are two solutions:
order by len(price), price
This works assuming that all the price values have the same structure.
Or:
order by cast(price as float)
If you could have non-numeric values (always a danger when storing numbers in the wrong data type):
order by (case when isnumeric(price) = 1 then cast(price as float) end)
Or better yet:
alter table alter column price money
Then you don't have to worry about having the wrong type for the column.

Your problem is Endprice columns is varchar(50), therefore it is comparing strings not numbers, which means that a 9>1 no matter what cames next of the first digit. You have to convert it to a number before the max!
Also you really should consider in doing what #a_horse_with_no_name suggested change your column into a number like column type.
This is a example on how you solve your actual problem
select max(cast(endprice as money)) from sample
See it here: http://sqlfiddle.com/#!3/767f6/1
Note that I used . as a decimal separator it will depend on your database language setup.

Related

SQL - Select and return functions

I am using SQL*Plus. This is what I am to do: Using the BOOK_ORDER table, create a query using the correct function to return the order number, the date ordered, the date shipped, and a column representing the number of months between the two dates for all columns where a date shipped exists. Format the number returned from the function to display only two decimals, and give the column an alias of "Months Between".
NOTE: Be sure that all of the numbers in the fourth column are positive numbers
I've started it this way; however, I am a bit lost and confused in what I am doing.
SELECT BOOK_ORDER.ORDERID, BOOK_ORDER.ORDERDATE, BOOK_ORDER.SHIPDATE ||', ' ||
Can someone help?
The assignment clearly points to using the Oracle built-in function MONTHS_BETWEEN. It's in the documentation. Find out more.
select b.orderid
, b.orderdate
, b.shipdate
, round(months_between(b.orderdate, b.shipdate),2) as "months between"
from book_order b
where b.shipdate is not null
/
Please be sure to give SO credit when you hand in your homemwork.

Greatest date from list of date

I have this simple data base:
7/2/2013
7/13/2013
I write a simple SQL statement to select the greatest date from a list of date. I try to use the (max function) as follow:
select max([P_Date]) from [BalDB].[dbo].[tab_Product]
The result was incorrect; it gives me the smallest date not the greatest as follow:
7/2/2013
So please help me to know what is the problem in my SQL statement and how can I solve it
Problem: Get the greatest date from a list of date or compare it with local date and take the greater!!
The sql max function returns the largest value of the selected column, in your case since your data type is a nvarchar the largest value is what is alphabetically larger, which in this case is 7/2/2013 (since the "2" is greater then the "1" in "13").
What you need to do is basically what #David mentioned, either chance the data type of the column or if it isn't feasible then you can cast it in your query as a datetime
For example
select max(cast([P_Date] as datetime)) from [BalDB].[dbo].[tab_Product]
The max function is making this slower than it needs to be, try this.
select top 1 convert(datetime,P_Date) from [BalDB].[dbo].[tab_Product] order by convert(datetime,P_Date) desc
Now your dates should be date types, not varchars, but for the sake of querying your data as is, this will work.

SQL Server - Select between two number ranges in a varchar field with text and numbers

I have a table with ranges of numbers from 0-2000000. I can use a between statement to get the records of things if I do a BETWEEN 50 AND 100. That works.
But the problem I'm running into is since this column is a varchar if there are any records with a something in the string as "1FD32", I can't select between it. SQL server can't convert the "BETWEEN 50 AND 100" because it is looking for an int. How can i get all the records between these ranges, and ignore any with letters in them?
If you want to do a numeric comparison, the only way to guarantee no error is to use the CASE statement. This is the only SQL statement that guarantees the order of valuation (when not used with aggregation functions).
So, here is code that will work:
select *
from t
where (case when isnumeric(col) = 1 then cast(col as bigint) end) between 20 and 100
Note that if your numbers contain decimal points, then you will want to use DECIMAL or FLOAT instead.

Functioning of MAX in t-SQL for INT and VARCHAR Datatypes

Last morning, my manager gave me a new database where I had to write few SQL Stored procedures. There was a column MMs which was meant for numeric values so I had the understanding that Sql Function MAX will work on it. But this was not the case.
It was a varchar column holding numeric values randomly stored from 1 to 41. I was assuming that my SQL Statement: "SELECT MAX(MMS) FROM tbl" will give me 41 as the result but it came out to be 9.
Later I invested that MAX when used with string datatypes takes the first numeric letter from the column and then gives the MAX out of them.
Does anybody has the idea why it is happening?
From here:
http://msdn.microsoft.com/en-uk/library/ms187751.aspx
For character columns, MAX finds the highest value in the collating
sequence.
If you want to sort the contents of your column numerically, you can do something like:
ORDER BY len(mms), mms

SQL: selecting distinct substring from a field

I'm blacking out on my basic SQL and would appreciate a quick hand:
I have a SQLite table, with 2 columns: Datetime, and a string saying something like "call from 555-555-3344".
I need a simple query that will give me a count of all distinct phone numbers that called on a certain day.
If the field had contained just the number, I could have used Select Distinct on it. How do I do it if the value (phone number) is a substring in that field (though always the last 10 digits).
Assistance, as always, much appreciated.
Guy
You can use the following (I used 12 instead of 10 in order to include the separator -):
SELECT COUNT(DISTINCT SUBSTR(phone_nbr, -12))
FROM table
WHERE call_dt = :call_dt;