SQL join that not in grouped date - mysql

I have this user_activity table
user_id date
1 2020-01-01 08:00:00
2 2020-01-01 08:05:00
1 2020-01-02 08:00:00
and user table
user_id
1
2
3
I want to know the user that don't have activity on all date. like this
date user_id
2020-01-01 3
2020-01-02 2
2020-01-02 3
I'm trying this but can't figure it out how to grouped it with date
SELECT a.* FROM user_activity a
LEFT OUTER JOIN user u on a.user_id= u.user_id
where a.user_id is null
I already looking for the answer but there is no answer with grouped date

SELECT u.user_id, all_dates.date
FROM user u
CROSS JOIN (SELECT DISTINCT DATE(date) as date FROM user_activity) as all_dates
WHERE NOT EXISTS (
SELECT 1
FROM user_activity ua
WHERE ua.user_id = u.user_id
AND DATE(ua.date) = all_dates.date
)
->
user_id date
3 2020-01-01
3 2020-01-02
2 2020-01-02
Also created a fiddle for you to play with

Related

How to fetch count from the sub-table with multiple date

I have a user table
id
name
number
created_at
1
User1
102
2022-02-03
2
User2
103
2022-02-06
3
User3
123456
2022-02-07
4
User4
1234567
2022-02-07
5
User5
1234568
2022-04-08
and invite table
id
invited_by
invited_to_number
created_at
1
1
123456
2022-04-05 12:03:03
2
2
123456
2022-04-05 17:13:23
2
1
1234567
2022-04-07 17:13:23
2
1
1234568
2022-04-07 17:13:23
2
2
1234565
2022-04-08 17:13:23
I need user table records along with the count of all invited registered in
all-time accepted in
Today accepted in
yesterday accepted in
with the group by number using MySQL Query
Count will only go to those users who were invited first
and after successfully registered count will add to the invited the user
So, the Expected result is
Today Date: 2022-04-08
id
name
all_time_accepted
Today's accepted
yesterday accepted
1
User1
3
1
1
2
User2
0
0
0
3
User3
0
0
0
4
User4
0
0
0
5
User5
0
0
0
If you want to count only today's or yesterday's invites, place a boolean condition (like DATE(i.created_at) = #today_date) inside the select expression. The condition will evaluate to 1 (if true) or 0 (if false), which means that if you SUM(), you will get the number of rows satisfying this condition.
SELECT
u.id,
u.name,
SUM(
u1.id IS NOT NULL
AND i1.id IS NULL
) AS all_time_accepted,
IFNULL(SUM(
u1.id IS NOT NULL
AND i1.id IS NULL
AND DATE(i.created_at) = #today_date
), 0) AS today_accepted,
IFNULL(SUM(
u1.id IS NOT NULL
AND i1.id IS NULL
AND DATE(i.created_at) = #today_date - INTERVAL 1 DAY
), 0) AS yesterday_accepted
FROM
(SELECT #today_date := CURDATE()) AS var,
`user` u
LEFT JOIN `invite` i
ON i.invited_by = u.id
LEFT JOIN `user` u1
ON u1.number = i.invited_to_number
LEFT JOIN `invite` i1
ON i1.invited_to_number = i.invited_to_number
AND i1.created_at < i.created_at
GROUP BY u.id

MySQL SUM two columns then another column with the net amount

Hi ive tried all the solution on stack over flow to no avail
i have 2 tables with a ID primary key, then date, and amount. there can be multiple dates of the same date in the table. the debits uses negative numbers in debits table
table "credits"
id | date | amount
1 2020-01-01 10.00
2 2020-01-02 20.00
3 2020-01-03 30.00
4 2020-01-01 10.00
5 2020-01-02 10.00
6 2020-01-03 10.00
table "debits"
id | date | amount
55 2020-01-01 -5.00
56 2020-01-02 -5.00
57 2020-01-03 -5.00
58 2020-01-01 -5.00
59 2020-01-02 -5.00
60 2020-01-03 -5.00
I want to return a 3 column result like so, grouped by DATE with 4 fields, date, amount credits (for teh day) amount debits (for the day) and the amont total (for the day)
date | amount_credits | amount_debits | amount_total
2020-01-01 20 10 10
2020-01-02 30 10 20
2020-01-03 40 10 30
I would do this using union all and aggrgtion:
select date, sum(credit) as credits, abs(sum(debits)) as debits),
sum(credits) + sum(debits) as net
from ((select c.date, c.amount as credit, 0 as debit
from credits c
) union all
(select c.date, 0, d.amount
from debits d
)
) cd
group by date;
I note that the sign of the debits amount changes, from the source table to the result set, which is why the outer query uses abs().
In particular, using union all and group by ensures that all dates in the original data are in the result set -- even if the date in in only one of the tables.
I'd group both tables on the date and then join the two:
SELECT c.date, amount_credits, amount_debits, amount_credits - amount_debits AS amount_total
FROM (SELECT date, SUM(amount) AS amount_credits
FROM credits
GROUP BY date) c
JOIN (SELECT date, -1 * SUM(amount) AS amount_debits
FROM debits
GROUP BY date) d ON c.date = d.date

Add value from other value with diffrent date in mysql

I have some problem in mysql, I have data like this
id
date
renewaltime
111
2020-01-01
1
111
2020-01-02
1
111
2020-01-03
1
111
2020-01-04
1
111
2020-01-05
1
but I wanna output be like this in mysql
id
date
renewaltime
renewal_by_date
111
2020-01-01
1
1
111
2020-01-02
1
2
111
2020-01-03
1
3
111
2020-01-04
1
4
111
2020-01-05
1
5
adding the value with value before in diffrent datetime
SELECT
h.id as ID,
i.date as DATE,
count(it.relid) as RENEWALTIME
FROM tblhosting h
INNER JOIN tblinvoiceitems it on h.id=it.relid
INNER JOIN tblinvoices i on it.invoiceid=i.id
WHERE h.id =305864
and i.status = 'Paid'
AND it.type = 'Hosting'
AND h.regdate <> it.duedate
GROUP BY i.date
please if you have same problem and share withme
thanks
On MySQL 8+, this is a cinch with analytic functions:
SELECT h.id, i.date,
SUM(COUNT(it.relid)) OVER (ORDER BY i.date) RENEWALTIME
FROM tblhosting h
INNER JOIN tblinvoiceitems it ON h.id = it.relid
INNER JOIN tblinvoices i ON it.invoiceid = i.id
WHERE
h.id = 305864 AND
i.status = 'Paid' AND
it.type = 'Hosting' AND
h.regdate <> it.duedate
GROUP BY
i.date
ORDER BY
i.date;

Get user who had no activity in from last 12 months

I want to make SQL that will return users who not performed any points/redeem activity in last 12 months
user_data
userId email create_date
1 steve#gmail.com 2017-01-05 12:55:00
2 mark_nel#gmail.com 2019-05-15 12:13:00
3 les.born#gmail.com 2018-04-05 03:15:00
points_data
id user_id activity_id activity_points create_date
1 1 1 10 2017-01-05 11:09:00
2 2 1 15 2019-06-12 09:17:00
3 2 2 10 2019-08-05 02:55:00
4 3 1 10 2019-01-05 07:15:00
redeem_data
id user_id redeem_points create_date
1 2 20 2019-09-11 02:55:00
Result
email
steve#gmail.com
Use LEFT JOIN concept to include non matching row from table user_data and only select non matching row by removing matching rows using where id of both tables(points_data,redeem_data) is null.
SELECT u.email
FROM user_data u
LEFT JOIN points_data p ON u.userId = p.user_id AND p.create_date >= CURRENT_DATE - INTERVAL 1 YEAR
LEFT JOIN redeem_data r ON u.userId = r.user_id AND r.create_date >= CURRENT_DATE - INTERVAL 1 YEAR
WHERE p.id IS NULL AND r.id IS NULL;

MySQL: total users in DB aggregated over date

I need to calculate total number of users "aggregated", day by day, ex:
table users:
id create_date
0 2016-09-01 00:00:00
1 2016-09-01 00:00:00
2 2016-09-01 00:00:00
3 2016-09-02 00:00:00
4 2016-09-02 00:00:00
5 2016-09-02 00:00:00
6 2016-09-03 00:00:00
7 2016-09-03 00:00:00
8 2016-09-04 00:00:00
9 2016-09-04 00:00:00
using the following query:
select date(u.create_date),count(u.id)
from user u
group by date(u.create_date)
returns:
date(u.create_date) count(u.id)
2016-09-01 3
2016-09-02 3
2016-09-03 2
2016-09-04 2
but I need to return data aggregated like this:
date(u.create_date) count(u.id)
2016-09-01 3
2016-09-02 6
2016-09-03 8
2016-09-04 10
thx,
Note: table key "id" has holes, (Non-sequentially).
You want a cumulative sum. In MySQL, this is probably easiest using variables:
select dte, cnt, (#c := #c + cnt) as running_cnt
from (select date(u.create_date) as dte, count(u.id) as cnt
from user u
group by date(u.create_date)
) d cross join
(select #c := 0) params
order by dte;
Note: When using aggregation with variables, I find that the subquery is necessary.
You could also do:
select d.dte,
(select count(*)
from users u
where u.create_date < date_add(u.dte, interval 1 day)
) as running_cnt
from (select distinct date(u.create_date) as dte from user u) d;
For small amounts of data, this is fine performance-wise.