How to join these tables? - mysql

I have three tables in a database, as follows:
users:
user_id name pbal
1 m1 100
2 m2 200
3 m3 300
4 m4 400
5 m5 500
payouts:
id user_id amount
1 1 100
2 1 200
3 2 300
4 1 400
blocked:
id user_id status
------ -------- ------
1 2 block
2 3 block
Now I want to make a list that excludes users whose user_id is in the blocked table, and that calculates a new total amount based on the pbal from users and the amount from the related rows in payouts:
name total_amount
----- ------------
m1 800
m5 500
m4 400
I have been trying for half an hour, but failed. Can someone help me?

Here's an example:
SELECT u.name, u.user_id, MAX(u.pbal) + SUM(p.amount) AS total_amount
FROM dbo.Payouts p
INNER JOIN dbo.Users u ON u.user_id = p.user_id
LEFT OUTER JOIN dbo.Blocked b ON u.user_id = b.user_id
WHERE b.user_id IS NULL
GROUP BY u.user_id, u.name
ORDER BY MAX(u.pbal) + SUM(p.amount) DESC;

Here is a possible answer:
SELECT u.name, u.user_id,
u.pbal + (
-- this takes amounts from the payouts table
SELECT SUM(p.amount)
FROM dbo.Payouts p
WHERE u.user_id = p.user_id
) AS total
FROM dbo.Users u
WHERE NOT EXISTS (
-- this excludes blocked users
SELECT *
FROM dbo.Blocked b
WHERE u.user_id = b.user_id
)
ORDER BY total;
I prefer subqueries in this case because they make it a bit more explicit

Related

Sum values from another table sql

I have an users table and amount table.
The users table has following columns.
name id
A 1
B 2
C 3
D 4
The amount table has following columns.
userId amount id
1 10 1
1 20 2
1 10 3
2 12 4
I need a sql which sums all the users amount from the amount table
Final output would be
name id totalAmount
A 1 30
B 2 12
C 3 0
D 4 0
I have tried using but does not work. Kindly help
let searchQuery = `SELECT u.id, u.name, (SELECT IFNULL(SUM(amount), 0) from amount WHERE amount.userId = u.id) as totalAmount, FROM users u LEFT JOIN amount amt on u.id = amt.userId WHERE`;
Correct syntax for correlated subquery version
SELECT u.id, u.name, (SELECT coalesce(SUM(a.amount), 0)
FROM amount a
WHERE a.userId = u.id) as totalAmount
FROM users u
You can do it using standard sql aggregation
select
u.name,
u.id,
sum(a.amount) as totalAmount
from users u
left join amount a
on a.userId = u.id
group by u.name, u.id
The left join is just to include those users whitout amounts, which will have a 0 as totalAmount

Export data from two tables, but only last record

I have a table user (reduced for clarity):
id
name
1
Joe
2
Bob
Then I have a table user_goal:
id
user_id
weight
1
1
111
2
1
333
3
1
222
4
2
120
5
2
190
I need combine data from those two tables and make an export for all users. I need to have a query that will provide me the following results:
name
weight
Joe
222
Bob
190
Please note that weight should be the last entered one.
I have made this query:
select u.name, ug.weigth
from user u
inner join user_goal ug on ug.user_id = u.id
group by ug.user_id
but the problem with it, is that it return the first entry in the user_goal. So it returns this:
name
weight
Joe
111
Bob
120
But it should return this:
name
weight
Joe
222
Bob
190
What do I need to change in this query?
Try next query:
select
u.name,
ug.weight
from users u
inner join user_goal ug on ug.user_id = u.id
inner join (
select max(id) last_id from user_goal group by user_id
) last_value on last_value.last_id = ug.id;
Test SQL online
In case MySQL 8.0 you can use window function row_number() as approach:
select name, weight from (
select
u.name,
ug.weight,
row_number() over (partition by ug.user_id order by ug.id desc) rn
from users u
inner join user_goal ug on ug.user_id = u.id
) t where rn = 1;
SQL here

MySQL query with join + count for a specific user in DB

I want to get the sum of several entities from several tables using a query.
Specifically, I want the devices and messages count of a user. In addition, the timestamp of the last received message for that user.
I have 3 tables:
Users
id name (other fields)
1 Mike ...
2 John ...
3 Yay ...
4 Jim ...
Devices
id user_id (other fields)
1 1 ...
2 1 ...
3 1 ...
4 2 ...
Messages
id device_id message time (other fields)
1 1 Hi 2019-04-07 12:06:44 ...
2 1 Hey 2019-04-06 12:06:44 ...
3 2 Sup 2019-04-05 12:06:44 ...
4 3 Ok 2019-04-04 12:06:44 ...
5 4 Yay 2019-04-08 12:06:44 ...
... and, for example, for user Mike I want to end up with:
Result
nDevices nMessages time
3 4 2019-04-07 12:06:44
Any ideas?
Thanks in advance.
Join the 3 tables and count distinct values of the columns:
select
count(distinct d.id) devicescounter,
count(distinct m.id) messagescounter,
max(m.time) lastmessagetime
from users u
left join devices d on u.id = d.user_id
left join nessages m on m.device_id = d.id
where u.name = 'Mike'
If you want the results for all users:
select
u.id, u.name,
count(distinct d.id) devicescounter,
count(distinct m.id) messagescounter,
max(m.time) lastmessagetime
from users u
left join devices d on u.id = d.user_id
left join nessages m on m.device_id = d.id
group by u.id, u.name
The easiest way to do this would be to get the number of messages and most recent message time for each device in a subquery.
SELECT u.id,
COUNT(d.id) AS num_devices,
SUM(messages) AS num_messages,
MAX(most_recent) AS most_recent_message
FROM users u
JOIN devices d ON d.user_id = u.id
JOIN (SELECT device_id,
COUNT() AS messages,
MAX(TIME) AS most_recent_message
FROM messages
GROUP BY device_id) m ON m.device_id = d.id
GROUP BY u.id
You could try using a join between user and device and a inner join with the subquery for message and device
select a.name, a.id, count(d.user_id), t.nDevice, t.max_time
from Users a
inner join device d on a.id = d.user_id
inner join (
select m.device_id, count(m.device_id) nDevice, max(m.time) max_time
from Messages m
group by m.device_id
) t on t.device_id = d.id
group by a.name, a.id

MYSQL JOIN query to group user skills for conditional count

I am struggling to find the logic for a JOIN query with GROUP BY.
I have 3 tables.
1. tbl_users
2. tbl_event_orders
3.tbl_event_signature ( For saving signatures on completed events)
tbl_users
id name skill
---------------------------
1 user1 A
2 user2 B
3 user3 A
4 user4 A
tbl_orders
id user_id item_id price
------------------------------------
1 1 1 100
2 2 1 100
3 3 1 100
4 4 1 100
tbl_signature
id item_id user_id signature
----------------------------------------------
1 1 1 xxxxxxxx...
1 1 3 NULL
1 1 4 xxxxxxxx...
I need the event details from item id.
For example for item with id 1, I need the following result.
skill total_count attended_users_count amount
A 3 2 300
B 1 0 100
skill - skill from user table.
total_count - total count of orders from that partical skill.
attended_users_count - total count of orders from that partical skill + this should have an entry and a NOT NULL value in tbl_signature table.
amount - sum of price(total_count)
I have the following query for getting users with skills and total count.
SELECT
U.skill as skill,
count(U.skill) as total_count,
sum( O.price ) as amount
FROM tbl_users U
INNER JOIN tbl_orders O
ON U.id = O.user_id
WHERE O.item_id = 1
GROUP BY U.skill
but when dealing with attended users count, I am getting unexpected results.
I have tried with the following query,
SELECT
U.skill as skill,
count(U.skill) as total_count,
count( S.signature ) as attended_users_count,
sum( O.price ) as amount
FROM tbl_users U
INNER JOIN tbl_orders O
ON U.id = O.user_id
LEFT JOIN tbl_signature S
ON O.item_id = S.item_id
WHERE O.item_id = 1
GROUP BY U.skill
Is there any way to get this in a single query?
This query should give you the results you want. It JOINs tbl_orders to tbl_users, and then LEFT JOINs to tbl_signature. Rows of tbl_signature which don't match, or which don't have a signature, will not get included in the count for that order:
SELECT u.skill,
COUNT(o.id) AS total_count,
COUNT(s.signature) AS attended_users_count,
SUM(o.price) AS amount
FROM tbl_orders o
JOIN tbl_users u ON u.id = o.user_id
LEFT JOIN tbl_signature s ON s.item_id = o.item_id AND s.user_id = u.id
WHERE o.item_id = 1
GROUP BY u.skill
Output:
skill total_count attended_users_count amount
A 3 2 300
B 1 0 100
Demo on dbfiddle

How to query the data between two table in this scenario?

There are three table, I mainly would like to query the transaction
User
-----
id
Debit
-----
id
amount
* user_id
create_date
Credit
------
id
amount
* user_id
create_date
So, I would like to get the transaction for particular user that order by the date, like the following
$150 1 2014-06-15 <== debit
$200 1 2014-06-16 <===credit
The problem is how to query? I need to join debit and credit together? Thanks for helping.
Use UNION ALL not JOIN since you want credit and debit rows separate. An extra join to table User if you want to get columns from it.
SELECT d.amount, d.create_date, 'debit' transactionType,
u.user_name
FROM Debit d
INNER JOIN User u
ON d.id = u.user_id
WHERE u.user_id = 1
UNION ALL
SELECT c.amount, c.create_date, 'credit' transactionType,
u.user_name
FROM Credit c
INNER JOIN User u
ON c.id = u.user_id
WHERE u.user_id = 1
ORDER BY create_date