I have table user with column login_time.
I want to select all the users that have logged in more than 10 times in a month.
I tried something like this:
SELECT login_time, count(id) as loginCount FROM user
WHERE login_time between DATE_SUB(login_time INTERVAL 1 month) AND login_time
GROUP BY id, MONTH(login_time) HAVING loginCount > 10;
Im not sure about my selection between dates.
How can I select with a month intervals avoiding double records.
For example if I have this values for login_time:
1. '2015-02-01 14:05:19'
2. '2015-01-21 14:05:19'
3. '2015-01-11 14:05:19'
Both 3 and 2 are within month range of 1.
So will I get double records for that values?
To find the users who have logged in more than ten times in the month ending right now, do this.
SELECT COUNT(*) times_logged_in,
userid
FROM user
WHERE login_time >= NOW() - INTERVAL 1 MONTH
GROUP BY user_id
HAVING COUNT(*)> 10
To find the users who have logged in more than ten times in any calendar month in your table, do this.
SELECT COUNT(*) times_logged_in,
DATE(DATE_FORMAT(login_time, '%Y-%m-01')) month_beginning,
userid
FROM user
GROUP BY user_id, DATE(DATE_FORMAT(login_time, '%Y-%m-01'))
HAVING COUNT(*)> 10
The trick here is the expression DATE(DATE_FORMAT(login_time, '%Y-%m-01')), which converts any timestamp to the first day of the month in which it occurs.
Your question mentioned this WHERE condition:
WHERE login_time between DATE_SUB(login_time INTERVAL 1 month) AND login_time
This doesn't do anything interesting because it always comes back true. Each given login_time always falls in the interval you specified.
Edit: You can GROUP BY MONTH(dt) if you want. But the way I have shown it automatically accounts for years as well as months, so in my opinion it's much better for accurate reporting.
Another edit: This formula yields the preceding Sunday for any given date or timestamp item.
FROM_DAYS(TO_DAYS(login_time) -MOD(TO_DAYS(login_time) -1, 7))
If Monday is the first day of the week in your jurisdiction, change the -1 to -2. Grouping by this function is superior to doing GROUP BY WEEK(login_time) because WEEK() does odd things at the beginnings and ends of calendar years.
This is all written up in more detail here: http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
Related
how can I count last 7 days data from SQL and group them by day/date (excluding today).
I should be able to use the result as $resultday1, $resultday2, $resultday3 etc.
If there was 10 total SQL entries in day 1 (yesterday) $resultday1 should show "10".
and the days should be last 7 only, and today/current day should not consider.
The following PHP SQL script shows the total count only
SELECT COUNT(1) FROM orders WHERE username='jondoe'
database is a list of referrals made by a registered user in previous days.
a single table contains all user's referral details, table name "orders" as per above example.
This is the exact query as you want
SELECT
COUNT(*), DATE(order_date) order_date
FROM
orders
WHERE
order_date < CURDATE()
AND order_date > DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY order_date
ORDER BY order_date DESC;
I'm trying to group a table of payments by an entire working day and payment method type (card, cash, stripe..). The thing is (and what I'm not able to accomplish) that a working day does not mean from 00:00 to 00:00 but instead it's a user input value (usually 08:00. I'm forcing 08:00 in the query now). This is because a Bar/Restaurant does not work from 00:00 to 00:00 but usually closes at 3 or 4 am. I also want to order the results by date (which I have already done).
This is the query I've gotten so far:
select * from (select SUM(value) as total, `currency`, `payment_method_type_id`, DATE_FORMAT(created_at, "%Y-%m-%d 08:00:00") as day from payments group by payment_method_type_id, DATE_FORMAT(created_at, "%Y-%m-%d 08:00:00"), currency) as ipd order by day desc
But results are not correct because time is not taken in account when grouping. I want from 08:00 of yesterday to 08:00 of today.
Here's a fiddle with the DB Schema and some inserts.
Thanks a lot,
To solve the problem, subtract 8 yours before changing to a date.
And it can be simplified to
SELECT SUM(value) as total, `currency`, `payment_method_type_id`,
DATE(created_at - INTERVAL 8 HOUR) as day
from payments
group by payment_method_type_id, day, currency
order by day desc
Perhaps you want the ORDER BY list to match the GROUP BY list?
I have a table in which there are 5 columns,
id (auto incrementing number), titleId, version, created_at
A combination of titleId and version is always unique. I want to find out for each day for the past 1 month, how many unique titleIds were present along with the count of how many entries per day. This is because on a given day there might be multiple versions of the same titleId.
select count(*) from titles where created_at >= '2019-08-12 00:00:00' and created_at <= '2019-08-13 00:00:00' will give me total number of titles which came on 12th August
and
select count(distinct titleId) from titles where created_at >= '2019-08-12 00:00:00' and created_at <= '2019-08-13 00:00:00'
will give me the count of unique titles on the 12th August. Is there a way for me to generate the data for the past 30/60 days?
I know I can run this command manually 30 times by changing the date to get the numbers, but was wondering if there is a better way to do this in mysql
As long as there is an entry every day, this query should give you the data for each day for the last 30:
select date(created_at) as cdate, count(distinct titleId) as cnt
from titles
where created_at >= cur_date() - interval 30 day
group by cdate
Score Table
user_idx (int)
date (datetime)
score (int)
I need to find out how much total score has increased over a week from today's date. I know that I need two of the same user tables grouped by user_idx that one contains total scores from the past to today and the other contains total scores from the past to a date of a week ago.
After that, by substracting one from the other will give me the answer... but I'm struggling to write effective sql query that does it.
I've tried
SELECT BLAH BLAH
FROM (SELECT user_idx, COUNT(*) as last_week_study_amount
FROM user_table
WHERE date <= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY user_idx)
AS a WHERE .....
Could you help me :( ?
Let me clear you want to get total count in last week.
Try below query
SELECT *
FROM (SELECT user_idx, COUNT(*) as last_week_study_amount
FROM user_table
WHERE date <= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY user_idx)
AS a WHERE .....
SELECT (SUM(score) - last_week_score) AS increased_score,
FROM user a
JOIN (SELECT b.user_idx, COUNT(*) as last_week_score
FROM userb
WHERE date<= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY b.user_idx) As c ON a.user_idx = c.user_idx
WHERE DATE(date) <= DATE(NOW())
GROUP BY a.user_idx
I ended up writing this code and I think this one is working okay... not sure if it's the best or has a critical error. I will update it if it turns out to be a bad one...
I have a query which returns total number of users registered on a particular days in 7 days interval time. I also want to get the zero count data so i can plot it on my graph. How to fetch zero count values?
The query :
select date(update_timestamp) as date, count(*) users
from registered
where date(update_timestamp) between date_sub(sysdate(), interval 7 day) and sysdate()
group by date(update_timestamp)
I had few problems with my query earlier which was solved on this post http://bit.ly/12irdyf .The problem is solved, however i need modification in my query, now i need to show null values as well.
Thanks
best way to keep a calender_table which has got entries for each date for the year.
select date(update_timestamp) as date, count(*) users
from calender_table c
left join registered r
on date(update_timestamp)=c.date
where c.date between date_sub(sysdate(), interval 7 day) and sysdate()
group by c.date
What do you mean by zero count values? Maybe you need:
select date(update_timestamp) as date, count(*) users, '0' AS zero
Maybe you wanted to fetch what date it was when you had no users?
Simply locate the date before the first user registered and assign a zero to it like above.