I am trying to figure out how to sort by time hourly with the following dataset.
hm,total_count,avg_count,max_count
-------------------------------------
'23:15','17','5.6667','9'
'23:45','19','3.1667','5'
'06:15','13','6.5000','9'
'05:15','22','4.4000','7'
'05:45','12','6.0000','11'
'04:15','22','4.4000','6'
'04:45','14','4.6667','7'
'03:45','24','2.4000','5'
'02:45','82','5.4667','13'
'01:45','98','6.1250','13'
'00:45','59','4.2143','11'
My query:
SELECT DATE_FORMAT(`dt`, '%H:%i') as hm, SUM(`counts`) AS total_count,
AVG(`counts`) AS avg_count, MAX(`counts`) AS max_count
FROM pax_load_distribution , plans
WHERE `pax_load_distribution`.`plan_id` = `plans`.`id` AND
`plans`.`dt` BETWEEN '2017-05-01' AND '2017-05-31'
GROUP BY hm
ORDER BY HOUR(hm) DESC, MINUTE(hm) ASC;
But as you can see, the query organize the 23 hours on top but not in a sequence from 23,00,01,02 etc. How can I make it such that the 23 hours are on top follow by 00,01 etc.
Try to use HOUR(dt + INTERVAL 1 HOUR) instead of HOUR(hm) DESC in your ORDER BY clause.
You can try : ORDER BY (HUOUR(hm) * 60 + MINUTE(hm)) ASC
Related
I have this mysql query that does what it needs to but it takes a really long time to load the content where as my other queries run perfectly fine and quick. Is there a better way to do it? I just want it to load faster. Here is my query:
SELECT
DISTINCT( # Without this I get too many results
CONCAT_WS(' ',
MONTHNAME(a.DateTimeViewed),
YEAR(a.DateTimeViewed)
)
) AS ViewedDate, # Displays as "January 2017" (example)
(
SELECT COUNT(b.ViewID)
FROM views b
WHERE
MONTH(b.DateTimeViewed) = MONTH(a.DateTimeViewed) AND
YEAR(b.DateTimeViewed) = YEAR(a.DateTimeViewed)
) as TotalViews
FROM views a
WHERE a.DateTimeViewed >= date_sub(now(), interval 6 month)
ORDER BY YEAR(a.DateTimeViewed) ASC, MONTH(a.DateTimeViewed) ASC
You are working too hard.
SELECT CONCAT_WS(' ', MONTHNAME(a.DateTimeViewed), YEAR(a.DateTimeViewed)
) AS ViewedDate,
COUNT(*) as TotalViews
FROM views a
WHERE a.DateTimeViewed >= date_sub(now(), interval 6 month)
ORDER BY YEAR(a.DateTimeViewed) ASC, MONTH(a.DateTimeViewed) ASC
Since you are backing up 6 months from this instant, you are getting the count for only part of the first month. Perhaps you want to change one line:
WHERE a.DateTimeViewed >= CONCAT(LEFT(CURDATE() - INTERVAL 6 MONTH, 7), '-01')
COUNT(*) is the usual way to count rows. COUNT(x) does the same, but adds on the effort to filter out rows with x IS NULL.
I'm having problems with my query, basically what I'm trying to do here is to order first by
item_info.content_time desc
and then by
item_views.views desc
My intention is to get the most recent items (order by item_info.content_time desc), with the most views (item_views.views desc). In essence something like the stackoverflow main page, where you have the most recent with the most views (I really don't know if that's how they are doing it). The following query either orders the items by one criteria or the other (if I reverse the order by criteria). Here's my code:
SELECT item_info.item_id, item_info.profile_id, item_info.tittle, item_covers.reference, usuarios.username, item_views.views
FROM item_info
LEFT JOIN item_covers ON item_covers.cover_id = item_info.book_id
LEFT JOIN usuarios ON item_info.profile_id = usuarios.id
LEFT JOIN item_views ON item_views.id = item_info.book_id
WHERE item_info.content_time
BETWEEN UNIX_TIMESTAMP( CURDATE( ) + INTERVAL -1
DAY )
AND UNIX_TIMESTAMP( CURDATE( ) + INTERVAL 1
DAY )
order by item_info.content_time desc, item_views.views desc
Roughly something like...
Expected output:
content_time | views
17:00 500
13:00 300
11:00 100
10:00 50
Actual output:
content_time | views
17:00 500
16:00 10
15:00 30
14:00 50
If you want a combination of the two you should create a column consisting of the combined (possibly weighed by an extra factor) sum of both like DATEDIFF(content_time,NOW())+views. By using DATEDIFF you will make sure that content_time is a numeric type and can be added to views. By using DATEDIFF()with the arguments in the shown order you will be getting a negative number for any content_times in the past which will reduce the combined value with views accordingly.
So your query should end in something like this
..
...
ORDER BY DATEDIFF(viewsitem_info.content_time,NOW())+viewsitem_info.views desc
DATEDIFF() gives the difference in days. Maybe you want to be a bit more precise. In that case you might want to use TIMESTAMPDIFF(MINUTE,viewsitem_info.content_time,NOW()) instead.
#Aaron: You will not have to change your data structure at all. If necessary you should introduce some kind of weighing factor like
ORDER BY
(0.123* TIMESTAMPDIFF(MINUTE,viewsitem_info.content_time,NOW())
+ viewsitem_info.view) DESC
write Your query like below
SELECT item_info.item_id, item_info.profile_id, item_info.tittle, item_covers.reference,
usuarios.username, item_views.views FROM item_info
LEFT JOIN item_covers ON item_covers.cover_id = item_info.book_id
LEFT JOIN usuarios ON item_info.profile_id = usuarios.id
LEFT JOIN item_views ON item_views.id = item_info.book_id
WHERE item_info.content_time
BETWEEN UNIX_TIMESTAMP( CURDATE( ) + INTERVAL -1DAY )
AND UNIX_TIMESTAMP( CURDATE( ) + INTERVAL 1
DAY )
order by item_info.content_time,item_views.views desc
I think it'll work.
I have this query to show a list of trending (most searched) names on my website:
SELECT name, COUNT(*) AS total_trends
FROM trending_names
WHERE dateTime BETWEEN '"&fromDate&"' AND '"&toDate&"' // -7 days to Now()
GROUP BY name
ORDER BY COUNT(*) DESC
LIMIT 10;
...and this is the kind of results I'm printing to screen:
(numbers represent quantity of searches made)
Angelina Jolie 31,293
Rihanna 26,722
Lindsay Lohan 18,351
Brad Pitt 11,901
I would now like to change the numbers to percentages; so I really need to be getting the total count of all trending names within the last 7 days, to calculate the correct percentage.
Is there a way I can add a total count to this query, without adding an additional query?
You can do in single query :
Try Below :
SELECT name, COUNT(*) AS total_trends,
sum(if(dateTime BETWEEN '"&fromDate&"' AND '"&toDate&"' ,1,0)) as total_last_7_days,
((sum(if(dateTime BETWEEN '"&fromDate&"' AND '"&toDate&"' ,1,0)) /COUNT(*) ) *100)
as percentage // if you want to get only percentage
FROM trending_names
GROUP BY name
ORDER BY COUNT(*) DESC
LIMIT 10;
You can use a subquery :
SELECT name, ((COUNT(*)*100)/(SELECT COUNT(*) FROM trending_names)) AS total_trends
FROM trending_names
WHERE dateTime BETWEEN '"&fromDate&"' AND '"&toDate&"' // -7 days to Now()
GROUP BY name
ORDER BY COUNT(*) DESC
LIMIT 10;
I know you aren't running SQL Server, but some readers might be interested to see this compact solution that's possible (SQL Server 2008 or later). I'm not sure many people know you can have a windowed aggregate that aggregates an aggregate.
select
name,
100.0*count(*)/sum(count(*)) over () as pct_trends
from trending_names
where dateTime between getdate()-7 and getdate()
group by name;
No, I don't think so. You do need to compute that total count on a separate (sub)select
SELECT name,(total_trends*100.0/sum_total_trends) pct_trends
FROM
(
SELECT name, COUNT(*) AS total_trends
FROM trending_names
WHERE dateTime BETWEEN '"&fromDate&"' AND '"&toDate&"' // -7 days to Now()
GROUP BY name
WITH ROLLUP
) A,
(
SELECT COUNT(*) AS sum_total_trends
FROM trending_names
WHERE dateTime BETWEEN '"&fromDate&"' AND '"&toDate&"' // -7 days to Now()
) B;
Lets say I have a table of messages that users have sent, each with a timestamp.
I want to make a query that will tell me (historically) the most number of messages a user ever sent in an hour.
So in other words, in any given 1 hour period, what was the most number of messages sent.
Any ideas?
Assuming timestamp to be a DATETIME - otherwise, use FROM_UNIXTIME to convert to a DATETIME...
For a [rolling] count within the last hour:
SELECT COUNT(*) AS cnt
FROM MESSAGES m
WHERE m.timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND NOW()
GROUP BY m.user
ORDER BY cnt DESC
LIMIT 1
If you want a specific hour, specify the hour:
SELECT COUNT(*) AS cnt
FROM MESSAGES m
WHERE m.timestamp BETWEEN '2011-06-06 14:00:00'
AND '2011-06-06 15:00:00'
GROUP BY m.user
ORDER BY cnt DESC
LIMIT 1
Need more details on table structure etc. but something like:
select date(timestmp), hour(timestmp) , count(*)
from yourtable group by date(timestmp) , hour(timestmp)
order by count(*) DESC
limit 100;
would give you hte desired result.
Something like this should work:
SELECT MAX(PerHr) FROM
(SELECT COUNT(*) AS PerHr FROM messages WHERE msg_uid=?
GROUP BY msg_time/3600) t
I suspect this would be horribly slow, but for an arbitrary historical max hour, something like this might work (downvote me if I'm way off, I'm not a MySQL person):
SELECT base.user, base.time, COUNT(later.time)
FROM messages base
INNER JOIN messages later ON later.time BETWEEN base.time AND DATE_ADD(base.time, INTERVAL 1 HOUR) AND base.user = later.user
WHERE base.user = --{This query will only work for one user}
GROUP BY base.user, base.time
ORDER BY COUNT(later.time) DESC
LIMIT 1
Consider the following table which has the fields - id (int) and date_created (datetime):
id date_created
1 2010-02-25 12:25:32
2 2010-02-26 13:40:37
3 2010-03-01 12:02:22
4 2010-03-01 12:10:23
5 2010-03-02 10:10:09
6 2010-03-03 12:45:03
I want to know the busiest/most popular hour of the day for this set of data. In this example, the result I'm looking for would be 12.
Ideas?
To get just the most popular hour, use this query
select date_format( date_created, '%H' ) as `hour`
from [Table]
group by date_format( date_created, '%H' )
order by count(*) desc
limit 1;
If you want to look at all the data, go with this one
select count(*) as num_records
, date_created
, date_format( date_created, '%H' ) as `hour`
from [Table]
group by `hour`
order by num_records desc;
If you want something a little more flexible, perhaps to the half hour, or quarter hour, you can do the following:
SELECT floor(time_to_sec(date_created)/3600),count(*) AS period
FROM table GROUP BY period ORDER BY c DESC
If you want the most popular 2 hour interval, use 7200. The most popular 15 minute interval, use 900. You just need to remember you are dealing with seconds (3600 seconds in an hour).
Use the hour() function to extract the hour, then do the usual aggregation:
SELECT count(hour(date_created)) AS c, hour(date_created) AS h FROM table GROUP BY h ORDER BY c DESC;
I like both Simon and Peter's answers, but I can't select both as accepted. I combined the 2 to make a cleaner query that only returned the popular hour (I don't need the counts).
SELECT hour(date_created) AS h
FROM my_table
GROUP BY h
ORDER BY count(*) DESC
LIMIT 1
You could try this:
SELECT
DATE_FORMAT(date,'%H') as hours,
count(*) as count
FROM
myTable
GROUP BY
hours
ORDER BY
count DESC