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

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

Related

MYSQL getting SUM through joins

I'm looking for a possible solution that will give me TOP 3 users from users table who are ordered based on the turnover they made.
So here is my table schema for users and transactions table.
users TABLE
id inviter_id
1 1
2 1
3 1
4 1
5 2
6 3
7 5
8 6
9 1
10 3
11 9
12 1
13 5
14 7
15 11
EXPLANATION : The id represents user's unique ID and inviter_id represents the ID that invited the user.
transactions TABLE
id payer _id amount
1 2 200
2 2 100
3 2 50
4 2 10
5 3 400
6 4 200
7 5 100
8 6 50
9 7 100
10 8 50
11 9 50
12 10 100
13 11 400
14 2 200
15 2 100
16 2 50
17 2 10
18 4 500
Here payer_id represents the users in users table.
Desired Output :
user_id turnover
//ID 1 should not be included in this table.
2 100 //ID 5 in `users` is referral of ID 2 so summing whatever ID 5 from `transactions` table using `payer_id` column we get : 100 (Sme process for other rows too)
3 150 //ID3's referrals : 6,10 | 50+100
4 0 //ID4's invited no one
5 100 //ID5's referrals : 7,13 | 100
6 50 //ID 6's referrals : 8 | 50
7 100 // ID 7's referrals : 14 | 0 (No rows for ID 14 in transactions table)
8 0 //No referrals invited
9 400 //ID9's referrals : 11 | 400
10 0 //No referrals invited
11 0 //ID11's referrals : 14 | 0 (No rows in txn table)
12 0 //No referrals invited
13 0 //No referrals invited
14 0 //No referrals invited
15 0 //No referrals invited
FIRST let me explain how I calculate turnover :
For each id from users table, Let's take id:1 as example. I check the 'inviter_id' column for 2. So whoever has the value as 2 in inviter_id column, those ids are considered as id 2's referral.
So I need the sum of amount all the referrals of id 2 has paid. Similarly for other ids and they should be sorted by the highest turnover.
What I tried so far :
here is my code.
select u.id AS user_id, u.address AS address, SUM(turnover) AS turnover
from users u left join
(select ur.id, ur.inviter_id, SUM(mt.userTurnover) as turnover
from users ur left join
(select m.payer_id, SUM(m.amount) as userTurnover
from matrix m where m.created >= $content_start AND m.type = 'escrow'
group by m.payer_id
) mt
on mt.payer_id = ur.id
where ur.created >= $content_start
group by ur.inviter_id
) ui
on ui.inviter_id = u.id
WHERE u.id != 1 AND u.id != 2 AND u.id != 3 AND u.id != 4
group by u.id
order by turnover desc LIMIT 10;
I'm getting the sum of amounts of the user itself instead of the user's each and every referral's paid amount.
SELECT u1.id, COALESCE(SUM(tr.amount), 0) turnover
FROM users u1
LEFT JOIN users u2 ON u1.id = u2.inviter_id
LEFT JOIN transactions tr ON u2.id = tr.payer_id AND u2.id != u2.inviter_id
GROUP BY u1.id
fiddle
If you need total payment sum for usrs.id = 1 (i.e. including self-referenced) then remove AND u2.id != u2.inviter_id.
If you do not need the final row for users.id = 1 then add according WHERE condition.

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;

JOIN MySQL tables based on condition

I have two MySQL tables users and task_reg
users
id name
1 user1
2 user2
3 user3
4 user4
5 user5
6 user6
7 user7
8 user8
9 user9
task_reg
top_id use_id payment
1 1 1
1 2 1
1 4 1
2 3 1
2 5 1
I have to display all the users and also show whether they have paid or not
here is my SQL command but it only shows the paid users
SELECT users.id, users.name, task_reg.payment
FROM task_reg
JOIN users ON users.id = task_reg.use_id
JOIN topics ON topics.id = task_reg.top_id
WHERE topics.id = 1
Result
id name payment
1 user1 1
2 user2 1
4 user4 1
Expected result
id name payment
1 user1 1
2 user2 1
3 user3 0
4 user4 1
5 user5 0
6 user6 0
7 user7 0
8 user8 0
9 user9 1
DB-Fiddle
Thanks.
Since you want all the users, it should be your first table in the join order.
Change your Inner join to Left Join.
Where condition on the topics.id should be a Join condition.
Use Coalesce() function to get value of payment done as 0 (because of no matching rows found).
Try:
SELECT users.id, users.name, COALESCE(task_reg.payment, 0) AS payment
FROM users
LEFT JOIN task_reg ON users.id = task_reg.use_id
LEFT JOIN topics ON topics.id = task_reg.top_id AND topics.id = 1

Retrieving the TOP 10 data with arithmetic operation

I want to retrieve the name of the user with the top 10 most voted post.
the formula in calculating the votes should be upvotes-downvotes. I also need to count the votes of that post.
Here's my
table user_info
id lname fname
1 abc1 abc1
2 abc2 abc2
3 abc3 abc3
4 abc4 abc4
5 abc5 abc5
6 abc6 abc6
7 abc7 abc7
table post
post_id post_message user_id
1 sup 1
2 good morning 2
3 hello 5
4 test 3
5 sample 4
table vote
vote_id user_id post_id vote_type
1 1 1 upvote
2 2 1 upvote
3 1 2 downvote
4 1 2 upvote
5 2 2 downvote
6 3 1 upvote
7 3 4 upvote
8 4 4 downvote
here's the query that I tried.
SELECT post_id, fname,lname,COUNT(CASE WHEN vote_type = 'upvote' then 1 ELSE NULL END) as "upvotes", COUNT(CASE WHEN vote_type = 'downvote' then 1 ELSE NULL END) as "downvotes"
FROM user_info
LEFT JOIN post ON
post.user_id = user_info.id
LEFT JOIN vote ON
post.user_id = user_info.id
ORDER BY 'upvotes'- 'downvotes' // is this possible?
LIMIT 10
My desired output is something like this.
post_id lname fname vote
1 abc1 abc1 3 // 3 upvotes
4 abc3 abc3 0 // 1upvote - 1 downvote
3 abc5 abc5 0 // no vote
5 abc4 abc4 0 // no vote
2 abc2 abc2 -1 // 1upvote - 2 downvotes
I don't know where I should put that column "vote" but it should be there in my query.
I created an sql fiddle for this
Fiddle
select p.post_id,u.fname,u.lname,
case when sum(upvotes)+sum(downvotes) is null then 0
else sum(upvotes)+sum(downvotes) end as vote
from post p left join
(
SELECT post_id,
CASE WHEN vote_type = 'upvote' then 1 ELSE 0 END as "upvotes",
CASE WHEN vote_type = 'downvote' then -1 ELSE 0 END as "downvotes"
FROM vote
) t
on p.post_id = t.post_id
left join user_info u on p.user_id = u.id
group by p.post_id
order by vote desc, sum(upvotes) desc, sum(downvotes) desc
limit 10;

Mysql SUM 0 when not in another table

I have 2 tables:
users:
id | name | club_id |
1 Bob 4
2 Jane 5
3 Alex 4
4 Paul 4
5 Tom 4
points:
user_id | club_id | amount(can vary)
1 4 10
1 2 10
2 5 10
3 4 10
3 4 10
4 4 10
3 2 10
3 4 10
I need (where users.club_id = 4 AND points.club_id = 4):
user_id | name | sum(amount)
3 Alex 30
1 Bob 10
4 Paul 10
5 Tom 0
Notice Tom is present in users but doesn't have any entries in points, so his sum should be 0. This is what throws me off in conjuction with grabbing a list from users.
Also would like this to be as efficient as possible (hence I added club_id = 4 both in users and points)
Try this:
SELECT
u.id,
u.name,
COALESCE(SUM(p.amount), 0) AS Totalpoints
FROM
(
SELECT *
FROM users
WHERE club_id = 4
) AS u
LEFT JOIN
(
SELECT *
FROM points
WHERE club_id = 4
) AS p ON p.user_id = u.id
GROUP BY u.id,
u.name;
See it in action here:
SQL Fiddle Demo
try this query
select u.id, u.name, sum(if (p.amount is null, 0, p.amount)) as totalPoint
from
user u
left join
(select * from point p where p.club_id = 4)p
on u.id = p.user_id
where u.club_id=4
group by u.id
SQL FIDDLE: