我需要让用户每天在MySQL中的访问持续时间。 我有这样的桌子:
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
并需要获得:
user_id,2018-09-01_duration,2018-09-03_duration
1,03:30:00,03:00:00
2,02:10:00,02:10:00
因此各列需要保持动态,因为某些日期可能会丢失(2018-09-02)。 每天可能有一个查询没有显式联接(某些日子可能为空)吗?
更新#1
是的,我可以在应用程序端生成列,但是我仍然遇到可怕的查询
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...
更新#2
是的,数据类似
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;
是正确的,但在这种情况下,用于用户的数据会保持一致。我希望能有这样一种方式,让我的用户行和带有日期的列(如上面的示例)
答案 0 :(得分:1)
尝试这样的事情:
select user_id, date, sum(time_end - time_start)
from table
group by user_id, date;
您将需要进行一些调整,因为您没有提到RDBMS提供程序,但是它应该为您提供一个清晰的思路。
答案 1 :(得分:1)
在MySQL中没有动态的方法来使用数据透视,但是您可能会use the following用于您的情况:
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;
答案 2 :(得分:0)
通过查询可以解决您的问题。查询是动态的,您可以对其进行改进。 我使用TSQL进行查询,您可以在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)
答案 3 :(得分:0)
如果知道结果集中所需的日期,则不需要动态查询。您可以只使用条件聚合:
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;
如果不知道结果集中所需的日期,则仅需要动态SQL。在这种情况下,我建议遵循与您想要的日期相同的结构。