Greatest date from list of date - sql

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.

Related

Select and manipulate SQL data, DISTINCT and SUM?

Im trying to make a small report for myself to see how my much time I get inputed in my system every day.
The goal is to have my SQL to sum up the name, Total time worked and Total NG product found for one specific day.
In this order:
1.) Sort out my data for a specific 'date'. I.E 2016-06-03
2.) Present a DISTINCT value for 'operators'
3.) SUM() all time registered at this 'date' and by this 'operator' under 'total_working_time_h'
4.) SUM() all no_of_defects registered at this 'date' and by this 'operator' under 'no_of_defects'
date, operator, total_working_time_h, no_of_defects
Currently I get the data I want by using the Query below. But now I need both the DISTINCT value of the operator and the SUM of the information. Can I use sub-queries for this or should it be done by a loop? Any other hints where I can learn more about how to solve this?
If i run the DISTINCT function I don't get the opportunity to sum my data the way I try.
SELECT date, operator, total_working_time_h, no_of_defects FROM {$table_work_hours} WHERE date = '2016-06-03' "
Without knowing the table structure or contents, the following query is only a good guess. The bits to notice and work with are sum() and GROUP BY. Actually syntax will vary a bit depending on what RDBMS you are using.
SELECT
date
,operator
,SUM(total_working_time_h) AS total_working_time_h
,SUM(no_of_defects) AS no_of_defects
FROM {$table_work_hours}
WHERE date = '2016-06-03'
GROUP BY
date
,operator
(Take out the WHERE clause or replace it with a range of dates to get results per operator per date.)
I'm not sure why you are trying to do DISTINCT. You want to know the data, no of hours, etc for a specific date.
do this....
Select Date, Operator, 'SumWorkHrs'=sum(total_working_time_h),
'SumDefects'=sum(no_ofDefects) from {$table_work_hours}
Where date='2016-06-03'
Try this:
SELECT SUM(total_working_time) as total_working_time,
SUM(no_of_defects) as no_of_defects ,
DISTINCT(operator) AS operator FROM {$table_work_hours} WHERE
date = '2016-06-03'

SQL Server : aggregate function doesn't work?

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.

Retrieving how many transactions were made on a date in SQL?

I have a table named Sales and a column within it named Date. I'm simply trying to find how many sales were made on a specific date. My intuition was to use something like this:
SELECT COUNT(Date) FROM Sales WHERE Date='2015-04-04'
this should count all sales that were made on that date, but that returns 0. What am I doing wrong?
While it is difficult to be precise without table definitions or an indication of what RDBMS you are using, it is likely that Date is a time/date stamp, and that the result you want would be obtained either by looking for a range from the beginning of the day to the end of the day in your WHERE clause, or by truncating Date down to a date without the time before comparing it to a date.
Try the below once.
select count(*) from <t.n> where date like '2015-04-04%';
When you want to find the count of rows based on a field (Date) You need to Group By over it like this:
SELECT Date, COUNT(*)
FROM Sales
GROUP BY Date
Now you have all count of rows for each Date.
Type and Value of Date is important in the result of the above query.
For example in SQL Server your best try is to convert a DateTime field to varchar and then check it as the result of CONVERT like this:
SELECT COUNT(*)
FROM Sales
WHERE CONVERT(VARCHAR, Date, 111) = '2015/04/04'

Average of DATE field in Teradata

I have a column of data in [DATE] format. It is a record of the first time an order was purchased. I am attempting to query the average date in this column. Meaning, I want to know what the average "first purchase" is.
Purchase_dt
01-01-2014
02-01-2014
03-05-2014
I need something to show what the average purchase_dt is.
Cheers
You can use a AVG on a DATE column, in fact it's using the same algorithm Tripp Kinetics mentioned. But it's probably using an INT as intermediate result, which soon results in a "numeric overflow"
For a larger number of rows you'll need to do the calculation manually like:
DATE '1900-01-01' + CAST(AVG(CAST(trans_date-DATE '1900-01-01'AS BIGINT)) AS INT)

Default value for datetime

How can you search for dates (datetimes) that contain a default value i.e. ''. I guess it is not:
select * from table where dateofbirth=''
All the dates seem to have a default value of '1900-01-01'. However, there are people in my database who have a date of birth on or before this date (histroic people mainly). Therefore I cannot do:
select * from table where dateofbirth='1900-01-01'
I know that some versions of SQL Server have a default date of: 1899-12-31.
I guess it is better to use nulls for unknown dates. I cannot do that in this case.
I have read through lots of questions on here about finding dates using SQL but I have not found an answer to my specific question.
You can get the default DateTime value as;
SELECT CONVERT(DATETIME, 0)
And apply it to the filter as appropriate;
SELECT * FROM [Table] WHERE DateOfBirth = CONVERT(DATETIME, 0)
Or if you need to select earlier dates then;
SELECT * FROM [Table] WHERE DateOfBirth <= CONVERT(DATETIME, 0)
Fiddle example
The best you are going to get is what you listed:
select * from table where dateofbirth='1900-01-01'
As you know, the problem is that if someone was really born on 1/1/1900, you will also include them. But there's really no way for your query to know the difference.
To fix this, you would need to change what your system is using for the default value (e.g. NULL or change to datetime2 or date datatype and use 1/1/0001). Then update all your 1/1/1900 values to the new default value. Yes, this will erroneously update any existing people with 1/1/1900 birthdays, but at least it will prevent any future occurrences.
In SQL Server terms a default value for column X is only used when a new record is first created and a value is not provided for that column. After the initial creation of the record the value is just a value, same as any other. Within a single table there is no way to distinguish between records that that hold the default value in column X because it was supplied, or because it was defaulted.
This won't help you now, but an alternative to nulls that is sometimes used is to use a 'magic value'. In the case of dates of births, the maximum datetime value of 31st December 9999 could be used to indicate an unknown value (assuming your system isn't expected to be in use in 8,000 years time :) Some people (including me) don't really approve of the use of magic values because there's no way in the database of indicating their magic status.
Rhys