Convert HOUR format into Day-Hour-Minute-Second in mysql - mysql

I am using this code am getting output in hours
with the below code.
Import script
CREATE TABLE `customerevent` ( `id` int NOT NULL, `Createddate` datetime DEFAULT NULL, `Modifiedate` datetime DEFAULT NULL, PRIMARY KEY (`id`) );
INSERT INTO customerevent (id, Createddate, Modifiedate) VALUES ('3', '2020-01-08 12:00:00', '2020-01-10 11:30:00');
CREATE TABLE holidays (
Id int NOT NULL AUTO_INCREMENT,
Holiday datetime DEFAULT NULL,
Account_of varchar(45) DEFAULT NULL,
PRIMARY KEY (Id));
My code :
SELECT d.Id, d.Createddate, d.Modifiedate,
SUM((TIMESTAMPDIFF(day, start_date, end_date) -
COALESCE((SELECT COUNT(*) FROM holidays WHERE holiday BETWEEN Createddate AND Modifiedate), 0))* 8 +
TIMESTAMPDIFF(minute, TIME(start_time), TIME(end_time)) / 60) task_time
FROM customerevent d
JOIN ( SELECT Id, DATE(Createddate) start_date, DATE(Modifiedate) end_date
, GREATEST('10:00:00', LEAST('18:00:00', TIME(Createddate))) start_time
, GREATEST('10:00:00', LEAST('18:00:00', TIME(Modifiedate))) end_time
FROM customerevent) dd ON dd.Id = d.Id GROUP BY d.Id;
present output:15.500
Expected output: 15H 30M
we have only 8 working hours per day so it is 15.500

Try This out
CREATE TABLE
customerevent (
id int NOT NULL,
Createddate CURRENT_TIMESTAMP() NULL,
Modifiedate CURRENT_TIMESTAMP()) NULL, PRIMARY KEY (id)
)

Related

SQL - Find Available Slots Within Date Range

I have following database schema:
CREATE TABLE `property` (
`id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL
);
CREATE TABLE `venue` (
`id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
`property_id` INT(11) NOT NULL,
`name` VARCHAR(100) NOT NULL
);
CREATE TABLE `venue_available` (
`id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
`venue_id` INT(100) NOT NULL,
`day` VARCHAR(10) NOT NULL,
`from_time` TIME NOT NULL,
`to_time` TIME NOT NULL,
`lead_time_in_minutes` INT(11)
);
CREATE TABLE `venue_unavailable` (
`id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
`venue_id` INT(100) NOT NULL,
`from_datetime` DATETIME NOT NULL,
`to_datetime` DATETIME NOT NULL
);
CREATE TABLE `venue_reservation` (
`id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
`venue_id` INT(100) NOT NULL,
`start_datetime` DATETIME NOT NULL,
`end_datetime` DATETIME NOT NULL
);
I want to find properties having venues available from 25th Aug(Sat) to 27th August (Mon) from 10am to 3pm
Here is the SQL query I tried
SELECT
p.id,
p.name AS property_name,
v.name AS venue_name
FROM
venue v
LEFT JOIN
property p ON v.property_id = p.id
-- venue_available
LEFT JOIN
venue_available va_0 ON va_0.venue_id = v.id
LEFT JOIN
venue_available va_1 ON va_1.venue_id = v.id
WHERE 1 = 1
-- venue_available
AND (
(va_0.day = 'sat' AND va_0.from_time <= '2018-08-25 10:00:00' AND va_0.to_time >= '2018-08-25 15:00:00') AND
(va_1.day = 'sun' AND va_1.from_time <= '2018-08-26 10:00:00' AND va_1.to_time >= '2018-08-26 15:00:00')
)
-- venue_unavailable
AND NOT EXISTS (SELECT * FROM venue_unavailable vu WHERE '2018-08-25 10:00:00' <= vu.to_datetime AND '2018-08-26 15:00:00' >= vu.from_datetime)
GROUP BY
p.id;
The problem with the current query is, the condition for venue_available in SQL query seems to work correctly, but when I add the condition for venue_unavailable it returns me the empty result, however based on the data I am expecting 1 result.
Here is the link to SQL fiddle, if you want to play around with schema and fixtures
http://sqlfiddle.com/#!9/33d60f/10
Here is what I am trying to do
1. Get the list of all properties (not venues)
2. List the property only if one or more venue is available after checking with
venue_available
venue_unavailable
venue_reservation
Can you help me with how to go about this?x
Thank you.
UPDATE1
I followed the following post to determine overlapping dates in venue_unavailable Select rows that are not between dates (reservation)
Alright, so the way I solved it is using sub query which is working now.
I am now using the WHERE clause with something like this
WHERE v.id NOT IN (SELECT venue_id FROM provider_block pb WHERE :start_datetime <= pb.to_date AND :end_datetime >= pb.from_date)
This seems to do the job for now.

How to calculate age in query?

How to calculate the age of the user inside a SQL query. Be aware I splitted the database into the fields: birthday, birthmonth and birthyear.
I created a fiddle to show what I mean.
CREATE TABLE IF NOT EXISTS `user_profile` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_birthday` tinyint(4) NOT NULL,
`user_birthmonth` tinyint(4) NOT NULL,
`user_birthyear` smallint(6) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
INSERT INTO `user_profile`
(user_birthday, user_birthmonth, user_birthyear) VALUES (31, 12, 1990)
SqlFiddleDemo
SELECT YEAR(NOW()) - YEAR(birthday) - (DATE_FORMAT(birthday, '%m%d') < DATE_FORMAT(NOW(), '%m%d')) AS Age
FROM (
SELECT
CAST(CONCAT(`user_birthyear`, '-', `user_birthmonth`, '-', `user_birthday`) AS DATE) AS birthday
FROM user_profile ) AS s
Year(getdate()) - birthyear shall be enough

False Positives outside date range in this mySQL JOIN

I am getting historical count data together in an automated report. The two main tables schemas are below. The third table referenced is person which has it's ids as foreign keys in email_list_subscription. That table's primary key consists of the two foreign keys email_list and person.
SQLFIDDLE HERE
The query below is coming up with a count which is outside the date ranges allowed in the query and I can't figure out why. It has rows for an email list that definitely has now rows in 2014 at all.
CREATE TABLE `email_list` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`handle` varchar(50) NOT NULL DEFAULT '',
`title` varchar(255) DEFAULT NULL,
`operator` varchar(255) DEFAULT NULL,
`operator_contact_name` varchar(255) DEFAULT NULL,
`operator_contact_email` varchar(150) DEFAULT NULL,
`operator_contact_phone` varchar(20) DEFAULT NULL,
`operator_listid` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `handle` (`handle`),
KEY `handle_2` (`handle`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `email_list_subscription` (
`email_list` smallint(5) unsigned NOT NULL DEFAULT '0',
`person` int(10) unsigned NOT NULL DEFAULT '0',
`as_email_address` varchar(150) DEFAULT NULL,
`datetime_synced_to_operator` datetime DEFAULT NULL,
`opted_in` datetime DEFAULT NULL,
`opted_out` datetime NOT NULL,
`undeliverable` datetime NOT NULL,
PRIMARY KEY (`email_list`,`person`),
KEY `email_list` (`email_list`),
KEY `person` (`person`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Here is a query dumped from the script and it's results checked directly in mySQL monitor:
SELECT
el.id, el.handle,
els.`email_list` ,
COUNT( els.person ) AS c
FROM
`email_list` el,
`email_list_subscription` els
WHERE
el.id = els.email_list
AND (
DATE( els.`datetime_synced_to_operator` ) >= '2014-04-01'
OR
DATE( els.`opted_in` ) >= '2014-04-01'
)
AND (
DATE( els.`datetime_synced_to_operator` ) <= '2014-05-18'
OR
DATE( els.`opted_in` ) <= '2014-05-18'
)
GROUP BY els.`email_list`
How is this capturing els rows whose dates are not in the range?
Those DATE() calls are going to kill your performance, much better to do
els.`datetime_synced_to_operator` >= '2014-04-01 00:00:00'
(for example).
Also, it is not clear your date ranges are going to work as intended; this seems more clear (but may have different results depending on data):
WHERE el.id = els.email_list
AND (
( els.`datetime_synced_to_operator` BETWEEN '2014-04-01 00:00:00' AND '2014-05-18 23:59:59')
OR
( els.`opted_in` BETWEEN '2014-04-01 00:00:00' AND '2014-05-18 23:59:59')
)
;
Also: What was wrong with the original where (below)?
AND (
DATE( els.`datetime_synced_to_operator` ) >= '2014-04-01'
OR
DATE( els.`opted_in` ) >= '2014-04-01'
)
AND (
DATE( els.`datetime_synced_to_operator` ) <= '2014-05-18'
OR
DATE( els.`opted_in` ) <= '2014-05-18'
)
Best illustrated with an example... any row with datetime_synced_to_operator any time after the start date (even after the end date) and an opted_in any time before the end date (even before the start date) gives true for this clause; and vice versa.

MySQL Incorrect datetime value: '09:40 AM' for column

I try to enter values to the table and i got this error
"Incorrect datetime value: '09:40 AM' for column"
CREATE TABLE Class_Section (
crn char(5) NOT NULL Primary key,
dept_code char(3) NOT NULL,
course_num char(3) NOT NULL,
meeting_days varchar(6) NULL ,
start_time datetime NULL,
end_time varchar(8) NULL,
campus_code varchar(3) NOT NULL,
location varchar(6) NOT NULL,
faculty_id char(4) NOT NULL,
enrollment TINYINT NOT NULL,
capacity TINYINT NOT NULL,
);
INSERT INTO Class_Section (
CRN, dept_code, course_num, meeting_days, start_time, end_time, campus_code, location, faculty_id, enrollment, capacity
)
VALUES ('20761', 'PSY', '101', 'MW', '09:40 AM', '11:10 AM', 'WC','E-527', 'F002', 40, 40
);
Thank you
Use Time Datatype
And You have used Comma at the end of column while creating table
CREATE TABLE Class_Section
(
crn char(5) NOT NULL Primary key,
dept_code char(3) NOT NULL,
course_num char(3) NOT NULL,
meeting_days varchar(6) NULL ,
start_time Time NULL,
end_time Time NULL,
campus_code varchar(3) NOT NULL,
location varchar(6) NOT NULL,
faculty_id char(4) NOT NULL,
enrollment TINYINT NOT NULL,
capacity TINYINT NOT NULL
);
INSERT INTO Class_Section ( CRN, dept_code, course_num, meeting_days, start_time, end_time, campus_code, location, faculty_id, enrollment, capacity ) values ('20761', 'PSY', '101', 'MW', '09:40:00', '11:10:00', 'WC','E-527', 'F002', 40, 40);
Fiddle Demo
Here's a SQL Fiddle for your question.
The start_time has a DateTime type which has a format of 'YYYY-MM-DD HH:MM'
specify the datetime field in this format
'9999-12-31 23:59:59'
assignment said start_time as datetime.
Unless you pass a date value, but the time, as part of a datetime field input, the engine won't understand just the time as a date and time. If you have pre-decided date and time on a course start date and end date, then input them in MySQL understandable formats.
If you have date and time values separately, you can combine them to form a datetime value.
Following are some examples:
Example 1:
If you have date and time as separate values:
insert into tbl( col_of_type_datetime ) values( curdate(), '09:40 AM' );
insert into tbl( col_of_type_datetime ) values( '2014-02-18', '09:40 AM' );
Example 2:
If you have a known timestamp value:
insert into tbl( col_of_type_datetime ) values( now() );
insert into tbl( col_of_type_datetime ) values( '2014-02-18 15:10:34' );
Example 3:
If you have only date but now time value:
insert into tbl( col_of_type_datetime ) values( cast( curdate() as datetime ) );
insert into tbl( col_of_type_datetime ) values( curdate() );
insert into tbl( col_of_type_datetime ) values( cast('2014-02-18' as datetime) );
insert into tbl( col_of_type_datetime ) values( '2014-02-18' );
Check that you have declared
start_time datetime ,
end_time varchar(8)
but while inserting, you are sending '09:40 AM', '11:10 AM' . So please check your datatypes once.
Because you declare start_time as datetime NULL, and mysql expects a datetime value.
Use the same type as end_time ( varchar(8) NULL)

select from multiple tables but ordering by a datetime field

I have 3 tables that are unrelated (related that each contains data for a different social network). Each has a datetime field dated- I'm already grouping by hour as you can see below (this one below for linked_in)
SELECT count(*), date_format(dated, '%Y:%m:%d %H') as hour
FROM upd8r_linked_in_accts
WHERE CAST(dated AS DATE) = '".$start_date."'
GROUP BY hour
I would like to know how to do a total across all 3 networks- the tables for the three are
CREATE TABLE IF NOT EXISTS `upd8r_facebook_accts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_id` varchar(50) NOT NULL,
`user_id` int(11) NOT NULL,
`fb_id` bigint(30) NOT NULL,
`dated` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=80 ;
CREATE TABLE IF NOT EXISTS `upd8r_linked_in_accts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_id` varchar(50) NOT NULL,
`user_id` int(11) NOT NULL,
`linked_in` varchar(200) NOT NULL,
`oauth_secret` varchar(100) NOT NULL,
`first_count` int(11) NOT NULL,
`second_count` int(11) NOT NULL,
`dated` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=200 ;
CREATE TABLE IF NOT EXISTS `upd8r_twitter_accts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_id` varchar(50) NOT NULL,
`user_id` int(11) NOT NULL,
`twitter` varchar(200) NOT NULL,
`twitter_secret` varchar(100) NOT NULL,
`dated` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
something like this ?
(SELECT count(*), date_format(dated, '%Y:%m:%d %H') as hour
FROM upd8r_linked_in_accts
WHERE CAST(dated AS DATE) = '".$start_date."')
UNION ALL
(SELECT count(*), date_format(dated, '%Y:%m:%d %H') as hour
FROM upd8r_facebook_accts
WHERE CAST(dated AS DATE) = '".$start_date."')
UNION ALL
(SELECT count(*), date_format(dated, '%Y:%m:%d %H') as hour
FROM upd8r_twitter_accts
WHERE CAST(dated AS DATE) = '".$start_date."')
UNION ALL
GROUP BY hour
update
the data in the actual database is not related by any pk or fk but the data is related that each table represents a user registering for a social network through the application and therefore i need to show the amount of users registered per hour across all three tables
update 2
the output of the query should show %Y:%m:%d %H and the amount of users registered (records created) that hour across the three tables.. each hour returning a new row (ordered by the time)
You are close to the solution
select t1.hourx, sum(t1.column1)
from (
(
SELECT count(*) as column1, date_format(dated, '%Y:%m:%d %H') as hourx
FROM upd8r_linked_in_accts
WHERE CAST(dated AS DATE) = '".$start_date."'
GROUP BY hourx
)
UNION ALL
(
SELECT count(*) as column1, date_format(dated, '%Y:%m:%d %H') as hourx
FROM upd8r_facebook_accts
WHERE CAST(dated AS DATE) = '".$start_date."'
GROUP BY hourx
)
UNION ALL
(
SELECT count(*) as column1, date_format(dated, '%Y:%m:%d %H') as hourx
FROM upd8r_twitter_accts
WHERE CAST(dated AS DATE) = '".$start_date."'
GROUP BY hourx
)
) t1
GROUP BY t1.hourx
I use 'hourx' to avoid reserve words, maybe not necessary.
I hope this works.
[ADD] This solution is called 'inline view'. You can google for that. It is supported by most of databases (mysql, oracle mssql and etc)