Resetting results when year changes - mysql

What I have:
Scenario 1:
SELECT `agent_id`, COUNT(`id`) AS total_users
FROM `users`
WHERE FROM_UNIXTIME(`create_at`, '%m-%d-%Y') <= '01-01-2016'
GROUP BY `agent_id`
Result:
agent_id | total_users
------------------------
foo | 0
bar | 0
Scenario 2:
SELECT `agent_id`, COUNT(`id`) AS total_users
FROM `users`
WHERE FROM_UNIXTIME(`create_at`, '%m-%d-%Y') <= '12-31-2015'
GROUP BY `agent_id`
Result:
agent_id | total_users
------------------------
foo | 532
bar | 435
The problem
The total_users column for the date 01-01-2016 is always 0. But when I change the value from 01-01-2016 to 12-31-2015, the value is different, it returns many users. It looks like that the data messes up when the year changes.

In you example:
FROM_UNIXTIME(`create_at`, '%m-%d-%Y') <= '01-01-2016'
It is not compared as DATE, but as string. That is why 01... gives 0 while 12... gives many rows. Because 12 is bigger than 01 as a string.
Therefore, to make it right, you can covert both to a DATE format:
SELECT `agent_id`, COUNT(`id`) AS total_users
FROM `users`
WHERE FROM_UNIXTIME(`create_at`) <= STR_TO_DATE('01-01-2016','%m-%d-%Y');
GROUP BY `agent_id`

This is solution, convert your comparision date to unix time stamp and check with create_at
SELECT `agent_id`, COUNT(`id`) AS total_users
FROM `users`
WHERE `create_at` <= UNIX_TIMESTAMP('01-01-2016')
GROUP BY `agent_id`
and
SELECT `agent_id`, COUNT(`id`) AS total_users
FROM `users`
WHERE FROM_UNIXTIME(`create_at`, '%m-%d-%Y') <= STR_TO_DATE('01-01-2016','%m-%d-%Y')
GROUP BY `agent_id`;
in second query there is two function call FROM_UNIXTIME() and STR_TO_DATE() but in first query there is only one function call UNIX_TIMESTAMP(). which solution is suitable you can use
Hope this will work for you

Unless you use STR_TO_DATE to a date string while comparing with another date it is considered to be string comparison.
Try the following query please :
SELECT `agent_id`, COUNT(`id`) AS total_users
FROM `users`
WHERE FROM_UNIXTIME(`create_at`, '%m-%d-%Y') <= STR_TO_DATE('01-01-2016','%m-%d-%Y')
GROUP BY `agent_id`;
Check this too:
SELECT '01-01-2016' > '12-31-2015';
Result: 0 i.e. FALSE. [ Because it's string comparison not date comparison.]
Now look at this:
SELECT STR_TO_DATE('01-01-2016','%m-%d-%Y') > STR_TO_DATE('12-31-2015','%m-%d-%Y')
Result: 1 i.e. TRUE.[ Because it's a date comparison now.]

The answers above didn't work.
I don't know why but, this solution instead seemed to work:
instead of using
WHERE FROM_UNIXTIME(create_at, '%m-%d-%Y') <= '01-01-2016'
I just omitted the second parameter of the function and reformatted the date to Y-m-d
So my where clause now looks like this
WHERE FROM_UNIXTIME(create_at) <= '2016-01-01'
Weirdly it worked. Anyways, thanks for those who tried to help me.

Related

SQL: Get all hits for unique days (timestamps)

So I have a database table which contains id, action, timestamp for example. I want to get the unique days with corresponding hits/views.
Something like this:
Date ------ Hits
2018-01-10 5
2018-01-11 542
2018-01-12 74
My approach was this:
SELECT DISTINCT FROM_UNIXTIME (timecreated, '%d.%m.%y') AS 'date'
FROM `mdl_logstore_standard_log`
WHERE action = 'viewed'
That lists me all unique days but if I'll add count(action) AS 'hits' to the SELECT statement it will just show me the first day with the sum of all hits.
How can I solve this query? I'm grateful for any hints
You need to group results using GROUP BY
SELECT FROM_UNIXTIME (timecreated, '%d.%m.%y') AS `date`, COUNT(action) AS hits
FROM `mdl_logstore_standard_log`
WHERE action = 'viewed'
GROUP BY FROM_UNIXTIME (timecreated, '%d.%m.%y')
ORDER BY `date`
For your requested output, you should really do:
SELECT FROM_UNIXTIME(timecreated, '%Y-%m-%d') AS `date`, COUNT(*) AS hits
FROM `mdl_logstore_standard_log`
WHERE action = 'viewed'
GROUP BY FROM_UNIXTIME (timecreated, '%Y-%m-%d')
ORDER BY MIN(timecreated);
The order by uses MIN(timecreated) so it will work even if you change the format.

How to select rows with the latest time for each date within the last 30 days from now

Imagine a table with field 'datetime'. Example rows:
2017-01-27 13:06:02
2017-01-27 05:13:14
2017-01-23 22:13:56
2017-01-26 14:02:09
2017-01-23 13:26:12
...
I need to get * from the bold lines, BUT WITHIN the last 30 days from now...
In other words, rows with the max date in the last 30 days.
30 rows in total in each case, assuming every day has at least one row...
You can group by the date part of datetime and get the max for each day.
select max(`datetime`)
from tablename
where `datetime` >= date(now())-interval '30' day
group by date(`datetime`)
To get all the fields from the table for such rows, use
select * from tablename where `datetime` in (
select max(`datetime`)
from tablename
where `datetime` >= date(now())-interval '30' day
group by date(`datetime`)
)
vkp's answer is basically correct, although there's no need for subquery to select the final result from - you can just put other columns straight into your query, up to something like this:
select *, max(datetime)
from tablename
where datetime >= date(now())-interval '30' day
group by date(datetime);
Ah, and that works for joins too.
The other thing I'd change to address the goal more precise, is:
max(time(datetime))
select * from your_table
where datetime between sysdate and sysdate-30

mysql query to find record filtering on the datetime

I have a table in which the following data structure is used:
col1 col2 timestamp
value1 value11 2014-27-04 03:05:25
value2 value22 2014-28-04 03:05:25
value3 value33 2014-27-04 04:05:25
Now I want to retrieve the rows which timestamp is greater than equal to 03:05:25 hours but that should be today's data...not the previous days data.
To avail this I have used the following query but this
select * from tab1 where time(timestamp) > '03:05:25';
But this returns all the data of previous days also. Any help on this is will be very helpful.
You could use
SELECT * FROM table WHERE TIME(timestamp)>01:01:01 AND DATE(timestamp) = DATE(NOW())
Wouldnt that fit your need?
Mel_T's will work too. Either use concat to bring it together or split it into 2 filters (time and date).
To select all rows of the same day but later than 03:05:25 you can do this:
select * from tab1 where timestamp > CONCAT(CURDATE(),' 03:05:25');
select
`timestamp` AS `timestamp`,
date(`timestamp`) AS `date`,
time(`timestamp`) AS `time`
from `timestamps`
where date(`timestamp`) = date(now()) AND time(`timestamp`) >= '03:05:25'
;

Multiple Select Subquery Count based on Hour of Day, Would Like to Add Table/Column

Right now, I have a multiple select subquery that is grabbing data based on hour of the day that's a count. What I want to do now, is to introduce another table into that query, and count based on an id as well as the datetime in the original table.
What I have right now is:
select
(
select count(a_date)
from t1
where d_date
between '2013-01-07 00:00:00' and '2013-01-07 00:59:59'
) AS '00:00 to 00:59',
(
select count(a_date)
from t1
where d_date
between '2013-01-07 01:00:00' and '2013-01-07 01:59:59'
) AS '01:00 to 01:59'
and so on, till the end of the day.
I have another query that's giving me the count based on the id and datetime, but there's only two columns, one which is showing the c_name and the other showing the count for the hour.
Ex.
select t2.c_name, count(t1.a_date)
from t2 join t1
on t2.t1_key = t1.t2_key
where t1.d_date
between '2013-01-07 00:00:00' and '2013-01-07 00:59:59'
group by t2.c_id
Basically, I'd like to combine these two queries into one that can show the c_name and all of the hours of the day.
Any suggestions?
I would look into using the CASE statement.
Try something like this (adding your additional 23 columns):
select c_name,
SUM(case when HOUR(d_date) = 0 then 1 else 0 end) '00:00 to 00:59',
SUM(case when HOUR(d_date) = 1 then 1 else 0 end) '01:00 to 01:59'
from t2
join t1 on t2.t1_key = t1.t2_key
group by c_name
And here is the SQL Fiddle.
You just need to add your WHERE criteria for d_date -- something like:
where d_date between '2013-01-07 00:00:00' and '2013-01-07 23:59:59'
or
where Date(d_date) = '2013-01-07'
Good luck!

MySQL Query not selecting correct date range

Im currently trying to run a SQL query to export data between a certain date, but it runs the query fine, just not the date selection and i can't figure out what's wrong.
SELECT
title AS Order_No,
FROM_UNIXTIME(entry_date, '%d-%m-%Y') AS Date,
status AS Status,
field_id_59 AS Transaction_ID,
field_id_32 AS Customer_Name,
field_id_26 AS Sub_Total,
field_id_28 AS VAT,
field_id_31 AS Discount,
field_id_27 AS Shipping_Cost,
(field_id_26+field_id_28+field_id_27-field_id_31) AS Total
FROM
exp_channel_data AS d NATURAL JOIN
exp_channel_titles AS t
WHERE
t.channel_id = 5 AND FROM_UNIXTIME(entry_date, '%d-%m-%Y') BETWEEN '01-05-2012' AND '31-05-2012' AND status = 'Shipped'
ORDER BY
entry_date DESC
As explained in the manual, date literals should be in YYYY-MM-DD format. Also, bearing in mind the point made by #ypercube in his answer, you want:
WHERE t.channel_id = 5
AND entry_date >= UNIX_TIMESTAMP('2012-05-01')
AND entry_date < UNIX_TIMESTAMP('2012-06-01')
AND status = 'Shipped'
Besides the date format there is another issue. To effectively use any index on entry_date, you should not apply functions to that column when you use it conditions in WHERE, GROUP BY or HAVING clauses (you can use the formatting in SELECT list, if you need a different than the default format to be shown). An effective way to write that part of the query would be:
( entry_date >= '2012-05-01'
AND entry_date < '2012-06-01'
)
It works with DATE, DATETIME and TIMESTAMP columns.