order by dates that match criteria - php

I have the following query that outputs the users that received the highest number of favorites in the past week in descending order:
SELECT COUNT(faves.user_id) AS topFaves, faves.created_on, user_name
FROM users
INNER JOIN faves ON faves.user_id= users.id
WHERE DATE_SUB(CURDATE(),INTERVAL 7 DAY) <= created_on
GROUP BY id ORDER BY topFaves DESC
I would like to be able to extend this list to contain all users, not just from the past week, but still order them by the same criteria (the number of favorites they got in the past week and not by the number of faves they have in total).
I tried to include a subquery in the select but didnt have any luck with it.
Thanks in advance for any help

Maybe I'm missing something, but just delete this line:
WHERE DATE_SUB(CURDATE(),INTERVAL 7 DAY) <= created_on
And you'll have "all users" - still sorting by topFaves...
Also if you want to list everyone (not just 10 people), you'll need to delete:
LIMIT 10

Related

How to write this subquery in Laravel

I have to group by the taken_date year to get the years and in the query I need to get the total work days and count of the order. Currently I am running this in MySQL procedure for executing this, but I sense there will be a better way to handle this, kindly let me know
select DATE_FORMAT(taken_date, '%Y') year, count(id) total, sum(total_days) total_days from
(
select id, taken_date, getNumOfWorkDays(order.order_num) total_days from order
where order.is_active = 1 and order.deleted_at is null
order by taken_date
) as order_years group by YEAR(taken_date) order by taken_date desc
Order Table columns looks like below
getNumOfWorkDays function will give you only work days based on start and end date of the order uses some other table to know the work days

Show all dates even those with zero data in it in mySQL?

My following query shows the date and the count of the emails found on each day (last 2 days)
My problem is that if no emails are found today, the today date will not be displayed on the output. (if yesterday has emails, it will show only 1 row with yesterday date and email).
How can I edit my query to always show 2 rows, today and yesterday, date and number of emails even zero?
SELECT maildate,
COUNT(*) AS totalEmails
FROM emails
WHERE maildate >= Date_add(Curdate(), interval - 2 DAY)
AND company_id = 1
GROUP BY DATE(maildate)
ORDER BY maildate desc
There are many tricks to creating a list of dates (or numeric sequences similarly). The one I like to use with MySQL is using #sqlvariables. I will typically start with a baseline value such as your date -2 days. I will do a cross-join to any other table in the database that has at least as many records as you expect in your output... Say 30 days, or a whole year 366 days, or longer. The inner sql variable prep will keep increasing itself by whatever increment (you could even do date ranges such as begin/end of a week, month, etc). Now you have your table of all possible dates you are looking to fill.
Now, I do a secondary query by the value -- in this case your email date and apply the group by. Using the where clause in this query will make IT faster since it can utilize the date on its query result set before returning for the LEFT-JOIN to the date range result set.
Now, your simple left-join gets both parts of all dates to be included and those corresponding counts that do exist.
Note the table alias "AnyTableWithAtLeast3RecordInIt" in the "JustDates" query could in-fact be your "emails" table. Since we don't care about any criteria except a record exists, and we are applying a limit of 30 days in my example, it will be instantaneous.
select
JustDates.DateToInclude,
coalesce( SumCnts.TotalEmails, 0 ) TotalEmails
from
( select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DateToInclude
from
( select #myDate := Date_add(Curdate(), interval - 2 DAY) ) as SQLVars,
AnyTableWithAtLeast3RecordInIt
limit 30 ) JustDates
left join
( select
maildate,
COUNT(*) AS totalEmails
FROM
emails
WHERE
maildate >= Date_add(Curdate(), interval - 2 DAY)
AND company_id = 1
GROUP BY
DATE(maildate) ) SumCnts
ON JustDates.DateToInclude = SumCnts.MailDate
Now, judging by your query, but unclarified request... Your emails table CAN HAVE FUTURE DATES? Is that correct? Such as a Dr. Office and appointments are for the future and you want to get emails out for a given range. This is what I was inferring and hence had my limit to only go out 30 days... If you need longer, just extend the LIMIT clause.
You need a table that contains all dates in the needed range. If its only about today and yesterday, you can easily create it as a subquery (derived table).
SELECT Curdate() as maildate
UNION ALL
SELECT Curdate() - INTERVAL 1 DAY
http://rextester.com/ALH50651
Now you can LEFT JOIN your table and count the rows:
SELECT sub.maildate,
COUNT(m.maildate) AS totalEmails
FROM (
SELECT Curdate() as maildate
UNION ALL
SELECT Curdate() - INTERVAL 1 DAY
) sub
LEFT JOIN emails m
ON DATE(m.maildate) = sub.maildate
AND m.company_id = 1
GROUP BY sub.maildate
ORDER BY sub.maildate desc

SQL: Select last 15 records from mysql grouped rows

Here is my query:
SELECT temp_table.*
FROM
( SELECT COUNT(*) as hits_count
, date
FROM visits
GROUP
BY date
) as temp_table
ORDER
BY temp_table.date ASC
LIMIT 15
I insert a new record into this table each time an user access a page. I need to get those records stacked by their date. It worked untill it hit the limit of 15 days, so now it doesn't show other days, it stops on his limit(15).
To make it clearer, let say I have stored 20 days, it shows just the 1-15 day interval, but i need it to get from db the interval 5-20, and so on.
I think this is what you are looking for:
SELECT temp_table.* FROM (
SELECT COUNT(*) as hits_count, date FROM visits GROUP BY date
) as temp_table ORDER BY temp_table.date DESC LIMIT 15
Not sure about the limit part though.

Unable to get count rows to work for 1 hour timespan in given date range

Using PHP and MySQL.
My DB structure is like so:
id, user, car, view_stamp
view_stamp is a TIMESTAMP like so: 2014-02-05 11:11:47
What I want to do is get the 'user' that has over 100 views in any given one hour span, in the past 24 hours.
This is my failed attempt at a loop query:
SELECT user, COUNT(id) AS TotalViews
FROM car_views
WHERE TotalViews > 100 AND view_stamp > DATE_SUB(NOW(),INTERVAL 1 DAY)
ORDER BY TotalViews DESC
LIMIT 10
The above does not have the 'One hour Span' requirement, and I don't know how to include it. It sounds confusing I'm sure, So let me try and rephrase just in case I made no sense above...
The time to check is just the past 24 hours. Within that 24 hour span, I need to know if any user viewed more than 100 times in any given 1 hour span.
Thanks for any help. If I am missing any useful info, please let me know and I will edit.
You need to use GROUP BY to get per-user, per-hour totals. And you have to use HAVING to test aggregate data.
SELECT user, HOUR(view_stamp) AS the_hour, COUNT(*) AS hourly_views
FROM car_views
WHERE view_stamp > DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY user, the_hour
HAVING hourly_views > 100
ORDER BY hourly_views DESC
LIMIT 10

MySQL ordering a date range to the beginning, then ordering everything else by other criteria

I have a table of items that have a "Date Created" field, and I'm trying to figure out a way to order them so that items created in the past two weeks appear first, and items that were not created in the last two weeks appear after that, sorted alphabetically.
I know how to do it with multiple sql queries, but I'd prefer not to do that if possible. Is it possible to do this?
select * from table
order by
case when date_created > curdate() - interval 2 week then 1 else 2 end,item
UPDATED ANSWER
(select * from table
where date_created > curdate() - interval 2 week
order by date_created desc limit 0,10000000000)
union all
(select * from table
where date_created < curdate() - interval 2 week
order by item
limit 0,10000000000)
LIMIT's use is necessary when you have to apply both asc and desc sorting within union.

Categories