mysql time to date conversion fetches null value - mysql

The below mentioned query is returning null but my inner query is fetching values like
SELECT CONCAT(
FLOOR(HOUR(time_milis) / 24), ' ',
MOD(HOUR(time_milis), 24), ':',
MINUTE(time_milis),':',
SECOND(time_milis))
FROM (
SELECT SUM(TIMEDIFF(logout_timestamp,login_timestamp)) AS time_milis FROM t_access_log WHERE logout_timestamp!='0000-00-00 00:00:00' GROUP BY login_id
)se
what am i missing here

Why not using DATE_FORMAT() for this? So my guess would be something like:
SELECT login_id ,
DATE_FORMAT(
SUM(
TIMEDIFF(
logout_timestamp,login_timestamp)
)
) as some_time
FROM t_access_log
WHERE logout_timestamp!='0000-00-00 00:00:00'
GROUP BY login_id;

Your time_milis are all seconds, but hour need a time like '10:05:03', you can just use sec_to_time. Like this:
SELECT concat(hour(sec_to_time(time_milis)), ' ', sec_to_time(time_milis))
FROM (
SELECT SUM(TIMEDIFF(logout_timestamp,login_timestamp)) AS time_milis FROM t_access_log WHERE logout_timestamp!='0000-00-00 00:00:00' GROUP BY login_id
)se

Related

why is time differences using alias not working?

SELECT
t.imei,
t.date,
t.time startTime,
t.ignition,
t.tripStartStop,
(
SELECT
min(time)
from
gps_data
where
time > t.time
and date >= t.date
and imei = '358480088853405'
and tripStartStop = 0
) ' stopTime',
SUBTIME('startTime', 'stopTime') AS diff
from
gps_data t
where
imei = '358480088853405'
and date >= '2020-03-08'
and date <= '2020-03-09'
and tripStartStop = 1
the above query returns startTime and stopTime as alias values but i can't get the difference of these two times
used both SUBTIME and TIMEDIFF
You cannot use aliases like that. The query:
SUBTIME('startTime','stopTime')
treats the startTime and stopTime as strings, hence the 00:00:00.
What you can do is following:
select q.imei, q.date, q.startTime, q.ignition,
q.tripStartStop, q.stopTime, subtime(q.startTime, q.stopTime)
from (
SELECT t.imei
, t.date
, t.time startTime
, t.ignition
, t.tripStartStop
, ( SELECT min(time) from gps_data where time>t.time and date>=t.date and imei='358480088853405' and tripStartStop=0 ) 'stopTime'
from gps_data t
where
imei='358480088853405'
and date between '2020-03-08' and '2020-03-09'
and tripStartStop=1
) as q
You need to select 'starTime' and 'stopTime' using select statement within the Substring. That would solve your problem.
SUBTIME(SELECT(startTime),SELECT(stopTime))
SELECT t.imei
, t.date
, t.time startTime
, t.ignition
, t.tripStartStop
, ( SELECT min(time) from gps_data where time>t.time and date>=t.date and imei='358480088853405' and tripStartStop=0 ) ' stopTime'
, SUBTIME(SELECT(startTime),SELECT(stopTime)) diff
from gps_data t
where imei='358480088853405'
and date>='2020-03-08'
and date<='2020-03-09'
and tripStartStop=1````

Get time duration per each available day

I need to get users visits duration for each day in MySQL.
I have table like:
user_id,date,time_start, time_end
1, 2018-09-01, 09:00:00, 12:30:00
2, 2018-09-01, 13:00:00, 15:10:00
1, 2018-09-03, 09:30:00, 12:30:00
2, 2018-09-03, 13:00:00, 15:10:00
and need to get:
user_id,2018-09-01_duration,2018-09-03_duration
1,03:30:00,03:00:00
2,02:10:00,02:10:00
So columns need to be dynamic as some dates can be missed (2018-09-02).
Is it possible to do with one query without explicit joins per each day (as some days can be null)?
Update #1
Yes, I can generate columns in application side, But I still have terrible query like
SELECT user_id, d1.dt AS "2018-08-01_duration", d2.dt AS "2018-08-03_duration"...
FROM (SELECT
user_id,
time_format(TIMEDIFF(TIMEDIFF(time_out,time_in),time_norm),"%H:%i") AS dt
FROM visits
WHERE date = "2018-09-01") d1
LEFT JOIN(
SELECT
user_id,
time_format(TIMEDIFF(TIMEDIFF(time_out,time_in),time_norm),"%H:%i") AS dt
FROM visits
WHERE date = "2018-09-03") d3
ON users.id = d3.user_id...
Update #2
Yes, data like
select user_id, date, SEC_TO_TIME(SUM(TIME_TO_SEC(time_out) - TIME_TO_SEC(time_in))) as total
from visits
group by user_id, date;
is correct, but in this case data for users goes consistently. And I hope there's the way when I have rows with users and columns with dates (like in example above)
Try something like this:
select user_id, date, sum(time_end - time_start)
from table
group by user_id, date;
You will need to do some tweaking, as you didn't mention the RDBMS provider, but it should give you a clear idea on how to do it.
There's no dynamic way to use pivotting in MySQL but you might use the following for your case :
create table t(user_id int, time_start timestamp, time_end timestamp);
insert into t values(1,'2018-09-01 09:00:00', '2018-09-01 12:30:00');
insert into t values(2,'2018-09-01 13:00:00', '2018-09-01 15:10:00');
insert into t values(1,'2018-09-03 09:30:00', '2018-09-03 12:30:00');
insert into t values(2,'2018-09-03 13:00:00', '2018-09-03 15:10:00');
select min(q.user_id) as user_id,
min(CASE WHEN (q.date='2018-09-01') THEN q.time_diff END) as '2018-09-01_duration',
min(CASE WHEN (q.date='2018-09-03') THEN q.time_diff END) as '2018-09-03_duration'
from
(
select user_id, date(time_start) date,
concat(concat(lpad(hour(timediff(time_start, time_end)),2,'0'),':'),
concat(lpad(minute(timediff(time_start, time_end)),2,'0'),':'),
lpad(second(timediff(time_start, time_end)),2,'0')) as time_diff
from t
) q
group by user_id;
If you know the dates that you want in the result set, you don't need a dynamic query. You can just use conditional aggregation:
select user_id,
SEC_TO_TIME(SUM(CASE WHEN date = '2018-09-01' THEN TIME_TO_SEC(time_out) - TIME_TO_SEC(time_in))) as total_20180901,
SEC_TO_TIME(SUM(CASE WHEN date = '2018-09-02' THEN TIME_TO_SEC(time_out) - TIME_TO_SEC(time_in))) as total_20180902,
SEC_TO_TIME(SUM(CASE WHEN date = '2018-09-03' THEN TIME_TO_SEC(time_out) - TIME_TO_SEC(time_in))) as total_20180903
from visits
group by user_id;
You only need dynamic SQL if you don't know the dates you want in the result set. In that case, I would suggest following the same structure with the dates that you do want.
By the query you can solve your problem. the query is dynamic and you can improve it.
i use TSQL for the query, you can use the idea in MySQL.
declare
#columns as nvarchar(max),
#query as nvarchar(max)
select
#columns =
stuff
((
select
distinct
',' + quotename([date])
from
table_test
for xml path(''), type
).value('.', 'nvarchar(max)'), 1, 1, '')
--select #columns
set #query =
'with
cte_result
as
(
select
[user_id] ,
[date] ,
time_start ,
time_end ,
datediff(minute, time_start, time_end) as duration
from
table_test
)
select
[user_id], ' + #columns + '
from
(
select
[user_id] ,
[date] ,
duration
from
cte_result
)
sourceTable
pivot
(
sum(duration)
for [date] in (' + #columns + ')
)
pivotTable'
execute(#query)

two column value in a single column using mysql query

I am getting output in different format, here is my query:
SELECT
COUNT(lead_id) AS `leads`,
Month(FROM_UNIXTIME(`created_at`)) AS `Month`
FROM `lead`
WHERE YEAR(FROM_UNIXTIME(`created_at`)) = YEAR(CURDATE())
GROUP BY Month(FROM_UNIXTIME(`created_at`));
Output:
Month
312c31
322c31
332c31
342c31
352c31
362c31
372c31
382c31
392c31
31302c31
31312c31
31322c31
Required Output:
month
1,1
2,23
3,4
5,6
6,34
7,76
8,2
9,3
10,5
11,4
12,1
You can try this:
SELECT
CAST(
CONCAT(
MONTH(FROM_UNIXTIME(`created_at`)),
',',
COUNT(lead_ID)
) AS CHAR
) AS 'Month'
FROM lead
WHERE `created_at` BETWEEN UNIX_TIMESTAMP(DATE_FORMAT(NOW(), "%Y-01-01")) AND UNIX_TIMESTAMP(DATE_FORMAT(NOW(), "%Y-12-31"))
GROUP BY MONTH(FROM_UNIXTIME(`created_at`))
i got an answer thankyou for all you replies ur replies also an usefull information here is my query
SELECT
*,
concat(leads, ",", month)as leadss
FROM (
SELECT
COUNT(lead_id) as 'leads,
Month(FROM_UNIXTIME(`created_at`)) AS `Month`
FROM `lead`
WHERE YEAR(FROM_UNIXTIME(`created_at`)) = YEAR(CURDATE())
GROUP BY Month(FROM_UNIXTIME(`created_at`))
)AS ab

Select in Concat mysql

I'm trying to get a date value with:
- Current year
- Current month
- Day number from one select
the query
SELECT rat_data FROM rate_unita WHERE rateid = 1
as a result one INT value.
When I try to execute the following:
SELECT DATE(CONCAT(YEAR(NOW())),(MONTH(NOW())), (SELECT rat_data FROM rate_unita WHERE rateid = 1))
Mysql mark my syntax as incorrect near ' ( MONTH( NOW( ) ) ) , ( SELECT rat_data FROM rate_unita WHERE r
I think that there is something wrong with the way I'm calling the SELECT in the CONCAT, what is the correct query to reach my goal?
Thanks
L
You're closing the concat function too early. Remove some extra parentheis
SELECT DATE(CONCAT(YEAR(NOW()),
MONTH(NOW()),
(SELECT rat_data FROM rate_unita WHERE rateid = 1)
))
But you need to add some hyphens to make it a true date value
SELECT DATE(
CONCAT(
YEAR(NOW()),
'-',
MONTH(NOW()),
'-',
(SELECT rat_data FROM rate_unita WHERE rateid = 1)
)
)
This should result in a date of YEAR-MONTH-rat_data
Here's a working SQL Fiddle
Use DATE_FORMAT function. Here are a few examples:
http://www.w3schools.com/sql/func_date_format.asp
http://www.mysqltutorial.org/mysql-date_format/

Mysql - Concat multiple INT fields together to make DATE field

I am working ona small project for a client, and the data in the database is causing me a bit of bother. I am completing a search form for paid installments from the database. I can get the data fine, its the date fields which are giving me bother.
There are separate fields for the date, month and year for each installments. Is there a way I can use CONCAT or DATE or maybe even use CAST on the combined fields to search for the data.
I have tried the following
SELECT DATE_FORMAT( CONCAT( received_date, received_month, received_year ) , '%d/%m/%Y' ) FROM policy_installments
AND
SELECT DATE_FORMAT(STR_TO_DATE(CONCAT('pit.received_date', '-', 'pit.received_month','-', 'pit.received_year'), '%d-%m-%Y') AS mydate, '%d-%m-%Y') AS modate FROM policy_installments pit ORDER BY mydate
AND
SELECT * FROM policy_installments WHERE CONCAT(CAST(received_date AS CHAR),"-",CAST(received_month AS CHAR),"-",CAST(received_year AS CHAR)) >= '1-1-2014' AND CONCAT(CAST(received_date AS CHAR),"-",CAST(received_month AS CHAR),"-",CAST(received_year AS CHAR)) <= '31-3-2014'
When I use the following I get some unexpected data:
SELECT CONCAT_WS( received_date, "-", received_month, "-", received_year ) FROM policy_installments
RESULT
2d313130312d3132303039
2d3237313032372d323732303039 etc etc
Each of the 3 fields are type INT(11).
However, none of these give me the correct data. Is there a way i can convert all 3 fields and use a date to pass into the query to enable me to correctly grab the correct data?
Any help would be much appreciated!
To convert a concatenated string to date, string should be in the same format as what you are using to convert.
For a date-string in dd/mm/yyyy format, should be converted to sql date using %d/%m%Y format.
Example:
SELECT STR_TO_DATE(
CONCAT( received_date, '/', received_month, '/', received_year ),
'%d/%m/%Y'
) as rcvd_date
FROM policy_installments
And to compare with other dates, you can use BETWEEN clause.
Example:
SELECT * FROM policy_installments
WHERE
STR_TO_DATE(
CONCAT( received_date, '-', received_month, '-', received_year ),
'%d-%m-%Y'
) BETWEEN STR_TO_DATE( '1-1-2014', '%d-%m-%Y' )
AND STR_TO_DATE( '31-3-2014', '%d-%m-%Y' )
Refer to:
MySQL: STR_TO_DATE(str,format): Convert a string to a date
Generally, you want to avoid performing the function on the column. Instead, perform the function on the literal, so that you can utilize indexes on the columns:
SELECT *
FROM policy_installments
WHERE received_year = YEAR('2014-03-31')
AND received_month = MONTH('2014-03-31')
AND received_date = DAY('2014-03-31')
Add a multi-column index on received_year, received_month, and received_date, you'll be doing pretty good.
Obviously, this method will only work for = comparisons. For <=, it becomes a bit more complicated:
SELECT *
FROM policy_installments
WHERE
received_year < YEAR('2014-03-31')
UNION
SELECT *
FROM policy_installments
WHERE
received_year = YEAR('2014-03-31')
AND received_month < MONTH('2014-03-31')
UNION
SELECT *
FROM policy_installments
WHERE
received_year = YEAR('2014-03-31')
AND received_month = MONTH('2014-03-31')
AND received_date <= DAY('2014-03-31')
But this longer query is still able to utilize the index.
To simplify things, consider creating an actual date column and keep it updated with the proper value.