In my query MYSQL CAST not working - mysql

I don't know what is wrong in my MYSQL query:
SELECT * FROM package_customers pc
left join installations ins on ins.package_customer_id = pc.id
WHERE pc.status = 'scheduled'
AND CAST(ins.schedule_date as DATE) >='10-27-2017'
The fields are:
status data type enum
schedule_date data type varchar
In the column schedule_date, the data is like this: 10-27-2017 12AM 12PM
I am trying to find date-wise data.

cast function can work if the source data is in acceptable format.
There are some conditions to validate date and time formats.
Your schedule_date column value does not match them. And hence, cast failed.
Please read documentation on Date and Time Types.
You should think of redesigning the table to include schedule_start and schedule_end columns with datetime data type. MySQL has various date and time functions to work with such data fields.
For time being, your varchar date data can be handled in following way.
mysql> SELECT #dt_string:='10-27-2017 12AM 12PM' AS dt_string
-> , #dtime:=STR_TO_DATE( #dt, '%m-%d-%Y %h%p %h%p' ) AS date_time
-> , DATE( #dtime ) AS my_date;
+-----------------------+---------------------+------------+
| dt_string | date_time | my_date |
+-----------------------+---------------------+------------+
| 10-27-2017 12AM 12PM | 2017-10-27 12:00:00 | 2017-10-27 |
+-----------------------+---------------------+------------+
1 row in set (0.00 sec)

Related

How to set date in mysql select

I have Mysql table:
id | deadline | days
1 | 1423695600 | 0
2 | 1426705199 | 1,2,3
I want: if days filed is 0, change deadline to today's date but keep old hour and minute
I have tried but i dont know how to bulid query
SELECT id IF(p.days != 0, deadline) as deadline, days FROM posts
I think you want to convert from unix time stamps to regular date times for this operation:
select addtime(date(now()), time(from_unixtimestamp(deadline))
You can get back a unix time stamp:
select unix_timestamp(addtime(date(now()), time(from_unixtimestamp(deadline)))
Try Case:
SELECT stock.name,
CASE
WHEN stock.quantity <20 THEN 'Buy urgent'
ELSE 'There is enough'
END
FROM stock

Difference between DATE and DATETIME in WHERE clause

Lets say, I have a table:
+------------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------+------+-----+-------------------+-----------------------------+
| id | int(10) | NO | PRI | | AUTOINCREMENT |
| id_action | int(10) | NO | IDX | | |
| a_date | date | NO | IDX | | |
| a_datetime | datetime | NO | IDX | | |
+------------+-----------+------+-----+-------------------+-----------------------------+
Each row has some id_action, and the a_date and a_datetime when it was executed on the website.
My question is, when I want to return COUNT() of each id_action grouped by a_date, is it same, when I use this two selects, or they are different in speed? Thanks for any explanation.
SELECT COUNT(id_action), id_action, a_date
FROM my_table
GROUP BY a_date
ORDER BY a_date DESC
and
SELECT COUNT(id_action), id_action, DATE_FORMAT(a_datetime, '%Y-%m-%d') AS `a_date`
FROM my_table
GROUP BY DATE_FORMAT(a_datetime, '%Y-%m-%d')
ORDER BY a_date DESC
In other words, my question is, that each action has its datetime, and if I really need column a_date, or it is the same using DATE_FORMAT function and column a_datetime and I dont need column a_date?
I ran both the queries on similar table on MySQL 5.5.
The table has 10634079 rows.
First one took 10.66 initially and always takes approx 10 secs on further attempts.
Seconds Query takes 1.25 mins to execute first time, on second, 3rd.... attempts its taking 22.091 secs
So in my view, if your are looking for performance, then you must have column a_date, as its taking half of the time when executed without Date_Format.
If performance is not the primay concern (like data redundancy can be) then a_datetime column will serve all other date/datetime related purposes.
DATE : The DATE type is used for values with a date part but no time part.
DATETIME: The DATETIME type is used for values that contain both date and time parts.
so if you have DATETIME you can always derive DATE from it but from DATE you can not get DATETIME.
And as per your sql there will not be a major difference.
It will be better not to have a_date because you already have a_datetime.
but in general if you can use TIMESTAMP you should, because it is more space-efficient than DATETIME.
Using a_date to group by day will be more efficient than a_datetime because of your conversion. In T-SQL I use a combination of DATEADD() and DATEDIFF() to get the date only from DATETIME since math is more efficient than data conversion. For example (again, using T-SQL though I'm sure there's something similar for MySQL):
SELECT COUNT(id_action), id_action,
DATEADD(DD,DATEDIFF(DD,0,a_datetime),0) AS [a_date]
FROM my_table
GROUP BY DATEADD(DD,DATEDIFF(DD,0,a_datetime),0) AS [a_date]
ORDER BY a_date DESC
This will find the number of days between day 0 and a_datetime then add that number of days to day 0 again. (Day 0 is just an arbitrary date chosen for it's simplicity.)
Perhaps the MySQL version of that would be:
DATE_ADD('2014-01-01', INTERVAL DATEDIFF('2014-01-01',a_datetime) DAY)
Sorry I don't have MySQL installed or I would try that myself. I'd expect it to be more efficient than casting/formatting but less efficient than using a_date.
If you are doing a function in your group by clause: "GROUP BY DATE_FORMAT(a_datetime, '%Y-%m-%d')", you will not be leveraging your index: "a_datetime".
As for speed, I believe there will be no noticeable difference between indexing on datetime vs date (but it's always easy to test with 'explain')
Lastly, you can always read a datetime as a date (using cast functions if need be). Your schema is not normalized if you have both a a_date and a_datetime. You should consider removing one of them. If date provides enough granularity for your application, then get rid of datetime. Otherwise, get rid of a_date and cast as required
As already mentioned, the performance of any function(o_datetime) will be worse than just a_date. The choice depends on on your needs, if there is no need to DATETIME, take a DATE and that is.
If you still need to find a function to convert, then I advise you to take a date().
See also How to cast DATETIME as a DATE in mysql?
Put the two statements in editor SQL and execute (CTRL-L) statistics.
https://technet.microsoft.com/en-us/library/ms178071%28v=sql.105%29.aspx
https://msdn.microsoft.com/pt-br/library/ms190287.aspx?f=255&MSPPError=-2147217396

Distinct TIME in SQL

My table has this field:
`processeddate` int(14) DEFAULT NULL,
a datetime converted by strtotime .
The content is like 1401847266
How do I select distinct this field which is an integer not a datetime?
I want to select per day.
Like the sum of member field ,registered, on 20140603 .
On database:
Member | Processed_Date
A | 1401847266 //real date 20140604
B | 1401846898 //real date 20140604
C | 1401844093 //real date 20140604
D | 1401788219 //real date 20140603
E | 1401788219 //real date 20140603
RESULT that I want to be displayed :
Date | Member
20140603 | 2
20140604 | 3
PS.
The processeddate is in datetime format converted into time integer, not date format.
You can use FROM_UNIXTIME() to convert the integer value to a datetime value and then use functions like YEAR() and MONTH() and DAY() on it. However when using a function on a column MySQL can't use an index anymore. Best is, to convert the other value like this:
...
WHERE your_column BETWEEN UNIX_TIMESTAMP('2014-06-04 00:00:00') AND UNIX_TIMESTAMP('2014-06-04 23:59:59');
EDIT:
What you want to do can be achieved with this query:
select
date(from_unixtime(Processed_Date)) as date, count(*) as member
from your_table
group by date
see it working live in an sqlfiddle

Workaround for unsupported date format when it comes to BETWEEN?

There's a date (its a varchar(30)) in a format, like this
d.m.y
, where
day = a day without leading zeros
m = a month with leading zeros
y = last two numbers of a year
And a table, that looks like this
id | date | price
1 | 7.04.14 | 10
2 | 8.04.14 | 20
3 | 9.04.14 | 30
And when a query is executed,
SELECT `price` FROM `table` WHERE `date` BETWEEN '7.04.14' AND '9.04.14';
it returns nothing
The thing: I cannot change a date format, and I have to get prices between two dates. Is there an easy way of doing this?
Just parse the dates.
SELECT price
FROM `table`
WHERE STR_TO_DATE(`date`, '%d.%m.%y')
BETWEEN STR_TO_DATE(...) AND STR_TO_DATE(...)
Also, consider taking a look at the manual page for STR_TO_DATE.
But as #juergen d writes, it is far better to use date types.

Group by day and still show days without rows?

I have a log table with a date field called logTime. I need to show the number of rows within a date range and the number of records per day. The issue is that i still want to show days that do not have records.
Is it possible to do this only with SQL?
Example:
SELECT logTime, COUNT(*) FROM logs WHERE logTime >= '2011-02-01' AND logTime <= '2011-02-04' GROUP BY DATE(logTime);
It returns something like this:
+---------------------+----------+
| logTime | COUNT(*) |
+---------------------+----------+
| 2011-02-01 | 2 |
| 2011-02-02 | 1 |
| 2011-02-04 | 5 |
+---------------------+----------+
3 rows in set (0,00 sec)
I would like to show the day 2011-02-03 too.
MySQL will not invent rows for you, so if the data is not there, they will naturally not be shown.
You can create a calendar table, and join in that,
create table calendar (
day date primary key,
);
Fill this table with dates (easy with a stored procedure, or just some general scripting), up till around 2038 and something else will likely break unitl that becomes a problem.
Your query then becomes e.g.
SELECT logTime, COUNT(*)
FROM calendar cal left join logs l on cal.day = l.logTime
WHERE day >= '2011-02-01' AND day <= '2011-02-04' GROUP BY day;
Now, you could extend the calendar table with other columns that tells you the month,year, week etc. so you can easily produce statistics for other time units. (and purists might argue the calendar table would have an id integer primary key that the logs table references instead of a date)
In order to accomplish this, you need to have a table (or derived table) which contains the dates that you can then join from, using a LEFT JOIN.
SQL operates on the concept of mathematical sets, and if you don't have a set of data, there is nothing to SELECT.
If you want more details, please comment accordingly.
I'm not sure if this is a problem that should be solved by SQL. As others have shown, this requires maintaining a second table that contains the all of the individual dates of a given time span, which must be updated every time that time span grows (which presumably is "always" if that time span is the current time.
Instead, you should use to inspect the results of the query and inject dates as necessary. It's completely dynamic and requires no intermediate table. Since you specified no language, here's pseudo code:
EXECUTE QUERY `SELECT logTime, COUNT(*) FROM logs WHERE logTime >= '2011-02-01' AND logTime <= '2011-02-04' GROUP BY DATE(logTime);`
FOREACH row IN query result
WHILE (date in next row) - (date in this row) > 1 day THEN
CREATE new row with date = `date in this row + 1 day`, count = `0`
INSERT new row IN query result AFTER this row
ADVANCE LOOP INDEX TO new row (`this row` is now the `new row`)
END WHILE
END FOREACH
Or something like that
DECLARE #TOTALCount INT
DECLARE #FromDate DateTime = GetDate() - 5
DECLARE #ToDate DateTime = GetDate()
SET #FromDate = DATEADD(DAY,-1,#FromDate)
Select #TOTALCount= DATEDIFF(DD,#FromDate,#ToDate);
WITH d AS
(
SELECT top (#TOTALCount) AllDays = DATEADD(DAY, ROW_NUMBER()
OVER (ORDER BY object_id), REPLACE(#FromDate,'-',''))
FROM sys.all_objects
)
SELECT AllDays From d