Mysql count from a second table - mysql

I have a query which grabs all users from the wait table based on $oneid. This works just fine but I would like to count how many messages a user leaves. These are in another table one_msg.
function waiting_users($oneid)
{
$query_str ="SELECT a.user_id, b.email, b.username, b.fbook, c.user_id as saved_user, d.type as user_type,
FROM wait a
LEFT JOIN users b ON a.user_id=b.id
JOIN user_profiles d ON a.user_id=d.user_id
LEFT JOIN save_one c ON a.user_id=c.user_id AND c.one_id=?
WHERE a.post_id = ?
ORDER BY a.date ASC";
}
$query = $this->db->query($query_str, array( $oneid, $oneid ) );
one_msg table
+----+--------+---------+---------+---------------------+
| id | one_id | host_id | user_id | date |
+----+--------+---------+---------+---------------------+
| 3 | 127 | 268 | 270 | 2012-06-11 18:57:58 |
| 4 | 127 | 268 | 270 | 2012-06-11 21:45:11 |
| 5 | 127 | 268 | 270 | 2012-06-12 09:10:01 |
+----+--------+---------+---------+---------------------+
So I am trying to count the messages from one_msg like this but it's returning the same value for all users.
function waiting_users($oneid)
{
$query_str ="SELECT a.user_id, b.email, b.username, b.fbook, c.user_id as saved_user, d.type as user_type,
(SELECT COUNT(id) FROM one_msg WHERE post_id = ?) AS count
FROM wait a
LEFT JOIN users b ON a.user_id=b.id
JOIN user_profiles d ON a.user_id=d.user_id
LEFT JOIN save_one c ON a.user_id=c.user_id AND c.one_id=?
WHERE a.post_id = ?
ORDER BY a.date ASC";
}
$query = $this->db->query($query_str, array( $oneid, $oneid, $oneid ) );

Your sub-query should check for the user_id instead of post_id (which does not exist in one_msg, so it is taken from wait:
(SELECT COUNT(id) FROM one_msg m WHERE m.user_id = a.user_id) AS count
instead of
(SELECT COUNT(id) FROM one_msg WHERE post_id = ?) AS count

Related

SUM two columns of two different tables in one result based group by id of another table

I have 3 tables:
Users:
id | account_name
-------------------|----------------------|
18 | panic |
Deposits:
id | user_id | amount
-------------------|---------------------------|
1 | 18 | 100
2 | 18 | 100
Withdrawals:
id | user_id | amount
------------------------|--------------------------------|
1 | 18 | 200
2 | 18 | 200
and i'm trying to get a result like:
id | totalDeposits | totalWithdraws
------------------------|---------------------------|
18 | 200 | 400
Now when i try to get the totals for some reason they are cross adding themselves up, of course if there are no rows it should return 0.
SELECT t0.id,IFNULL(SUM(t1.amount),0) AS totalWithdrawals,
IFNULL(SUM(t2.amount),0) AS totalDeposits
FROM users t0
LEFT OUTER JOIN withdrawals t1 ON (t0.id = t1.user_id)
LEFT OUTER JOIN deposits t2 ON (t0.id = t2.user_id)
GROUP BY t0.id
Any idea how to do this cross join or where am i summing them wrong?
Try this-
SELECT A.id,
(SELECT SUM(amount) FROM Deposits WHERE user_id = A.id) totalDeposits,
(SELECT SUM(amount) FROM Withdrawals WHERE user_id = A.id) totalWithdraws
FROM users A
WHERE A.id = 18 -- WHERE can be removed to get all users details
You can try something along the lines of
SELECT u.id,
COALESCE(d.amount, 0) totalDeposits,
COALESCE(w.amount, 0) totalWithdrawals
FROM users u
LEFT JOIN (
SELECT user_id, SUM(amount) amount
FROM deposits
GROUP BY user_id
) d ON u.id = d.user_id
LEFT JOIN (
SELECT user_id, SUM(amount) amount
FROM withdrawals
GROUP BY user_id
) w ON u.id = w.user_id
SQLFiddle
Result:
| id | totalDeposits | totalWithdrawals |
|----|---------------|------------------|
| 18 | 200 | 400 |
The problem is that you are generating a Cartesian product. One solution is to aggregate first. Another method is to use UNION ALL and GROUP BY. I would structure this as:
SELECT u.id,
SUM(deposit) as deposits,
SUM(withdrawal) as withdrawal
FROM users u LEFT JOIN
((SELECT d.user_id, d.amount as deposit, 0 as withdrawal
FROM deposits d
) UNION ALL
(SELECT w.user_id, 0, w.amount
FROM withdrawals w
)
) dw
ON u.id = dw.user_id
GROUP BY u.id;

Mysql select from subquery is not working

I want to create report of total number of orders and total earning that are belong to each users.
SELECT w.id, CONCAT_WS(' ', w.fname, w.sname) AS full_name,
te.total_earnings, te.assigned_jobs
FROM users AS w
LEFT JOIN (
SELECT wr.user_id,
COUNT(o.order_id) AS assigned_jobs,
SUM(o.fee) AS total_earnings
FROM (
SELECT DISTINCT user_id, order_id, withdrawn
FROM work_records
) AS wr
LEFT JOIN orders o ON o.order_id = wr.order_id
WHERE wr.withdrawn IS NULL
AND o.verified != 'rejected'
) AS te ON te.user_id = w.id
WHERE w.status = 1
orders work_records
___________________ _________________________________
| order ID | fee | | id | order_id | fee | user_id |
------------------- ---------------------------------
| 334 | 425 | | 1 | 334 | 50 | 6 |
| 2 | 334 | 50 | 6 |
This query works on single user id. But it doesn't work if I want to get report of all users.
Any advise thanks?
Here is the answer for others. How ever the query is slower. But if you have faster query would greate to share.
SELECT w.id, CONCAT_WS(' ', w.fname, w.sname) AS full_name,
te.total_earnings, te.assigned_jobs
FROM users AS w
LEFT JOIN (
SELECT w.id,
SUM(work.earnings) AS total_earnings,
COUNT(work.order_id) AS assigned_jobs
FROM users AS w
LEFT JOIN (
SELECT wr.order_id, wr.writer_id, o.fee AS earnings
FROM work_records wr
LEFT JOIN orders o ON o.order_id = wr.order_id
WHERE wr.withdrawn IS NULL
AND o.verified = 'verified'
GROUP BY wr.order_id
) work ON work.writer_id = w.id
GROUP BY work.writer_id
) te ON te.id = w.id

MySQL syntax issue, multiple SELECT statements

I am working of a project that has 2 tables as follows: users_fb and posts
I spent 3 hours playing with the code and then I gave up.
table: posts
+-----+---------+---------+---------+---------+-----------+
| id | by_user | by_page | votes | status | time |
+-----+---------+---------+---------+---------+-----------+
| 1 | 1 | 0 | 20 | 1 | 372041014 |
+-----+---------+---------+---------+---------+-----------+
table: users_fb
+-----+-----------+-------+---------+--------+-------+
| id | username | name | gender | fb_id | email |
+-----+-----------+-------+---------+--------+-------+
SELECT username,
(
SELECT COUNT(b.by_user)
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.username
) AS totalCount ,
(
SELECT IFNULL(SUM(b.votes),0)
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
GROUP BY users_fb.id
) AS total_votes
FROM users_fb ORDER BY total_votes DESC
The desired output
+-------------------+-------------+-------------+
| username | totalCount | total_votes |
+-------------------+-------------+-------------+
| user4 | 1 | 25 |
| user1 | 0 | 0 |
| user2 | 0 | 0 |
| user3 | 0 | 0 |
+-------------------+-------------+-------------+
UNFORTUNATELY: This is what I am getting
+-------------------+-------------+-------------+
| username | totalCount | total_votes |
+-------------------+-------------+-------------+
| user4 | 1 | 25 |
| user1 | 1 | 25 |
| user2 | 1 | 25 |
| user3 | 1 | 25 |
+-------------------+-------------+-------------+
If you need any further information, let me know. Thanks for your help.
You don't appear to have anything to join your tables together to match up with posts / votes go with which user.
Something like this should do it
SELECT users_fb.username, Sub1.postcount, Sub2.votecount
FROM users_fb
LEFT OUTER JOIN(
SELECT a.username, COUNT(*) AS postcount
FROM users_fb a
INNER JOIN posts b
ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.username
) Sub1
ON users_fb.username = Sub1.username
LEFT OUTER JOIN(
SELECT users_fb.id, IFNULL(SUM(b.votes),0) AS votecount
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user
GROUP BY users_fb.id
) Sub2
ON users_fb.id = Sub2.id
Possibly simplified to
SELECT a.username, SUM(IF(b.by_page = '0', 1, 0)) AS postcount, IFNULL(SUM(b.votes),0) AS votecount
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user
GROUP BY a.username
Since you are doing no matching of the selects (i.e. there is no binding WHERE between them), MySQL has no wait to make them show together.
You should do something like this:
SELECT username, totalCount.count, total_votesGROUPED.sum
FROM users_fb
LEFT JOIN (
SELECT COUNT(b.by_user) as count, a.username
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.username
) AS totalCount ON totalCount.username = users_fb.username,
(
SELECT IFNULL(SUM(b.votes),0) as sum, id
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
GROUP BY users_fb.id
) AS total_votesGROUPED ON total_votesGROUPED.id = users_fb.id
ORDER BY total_votes DESC
If I had a bit more information, I could test it
Quite a few problems, the biggest is that you don't make any join between your "main query" and your "subqueries".
So finally, something like that should be better.
SELECT
a.username,
SUM (CASE WHEN b.by_page IS NOT NULL and b.by_page = '0' then 1 else 0 end) as cnt,
SUM (IFNULL(b.votes),0) as nbVotes,
FROM users_fb a
LEFT JOIN posts b ON a.id = b.by_user
GROUP BY users_fb.id
SELECT a.username,
COUNT(b.by_user) totalCount,
SUM(IFNULL(b.votes,0)) total_votes
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.id,a.username
SELECT username, IFNULL(COUNT(b.by_user), 0) totalCount, IFNULL(SUM(c.votes), 0) total_votes
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user AND b.by_page = 0
LEFT JOIN posts c
ON a.id = b.by_user
GROUP BY username
SQLFIDDLE

Trouble with join statement for selecting data across tables with MYSQL

I'm trying to display events that a user has created and events that he has signed up for. I have three tables for this.
//events
| event_id | event_title | event_details | event_timestamp | userid
1 title1 test 1234 1
2 title2 testing2 123 2
//registration_items : event_id references events.event_id
| id | event_id | task_name
1 2 task 1
//registration_signup : id references registration_items.id
| id | userid | timestamp
1 1 1234
Here's the current query I have. Right now it only displays the event the user created. It should display both created events and ones he signed up for
select events.*, registration_items.*, registration_signup.*, users.username from events
INNER JOIN users on users.userid = events.userid
LEFT JOIN registration_items ON registration_items.event_id = events.event_id
LEFT JOIN registration_signup ON registration_signup.id = registration_items.id
WHERE events.userid = '$user_id' OR registration_signup.userid = '$user_id' ORDER BY events.event_timestamp DESC
For userid1 the output should be
Title
title1 (the user created this)
title2 (the user signed up for this)
For userid2 the output should be
Title
title2
select events.*, registration_items.*, registration_signup.*, users.username
from events
INNER JOIN users on users.userid = events.userid
LEFT JOIN registration_items ON registration_items.event_id = events.event_id
LEFT JOIN registration_signup ON registration_signup.id = registration_items.id
WHERE registration_signup.userid = '$user_id'
union
select events.*, registration_items.*, registration_signup.*, users.username
from events
INNER JOIN users on users.userid = events.userid
INNER JOIN registration_items ON registration_items.event_id = events.event_id
INNER JOIN registration_signup ON registration_signup.id = registration_items.id
WHERE events.userid = '$user_id'
ORDER BY events.event_timestamp DESC
I am not sure if it's correct to guess that you have a typo in the sample data. Because your query works the moment you change the user id to 1 for both events, signed up events.. So please take a look at this reference demo and comment if it's not a typo...
SQLFIDDLE DEMO
query: (your query..)
select u.userid,e.event_id as id,
ri.event_id as evt, e.event_title,
ri.task_name,
rs.timestamp,
u.name from events e
INNER JOIN users u on
u.userid = e.userid
LEFT JOIN registration_items ri ON
ri.event_id = e.event_id
LEFT JOIN registration_signup rs ON
rs.id = ri.id
WHERE e.userid = '1' or
rs.userid = '1'
ORDER BY e.event_timestamp DESC
;
Results:
| USERID | ID | EVT | EVENT_TITLE | TASK_NAME | TIMESTAMP | NAME |
------------------------------------------------------------------
| 1 | 1 | 1 | title1 | task 1 | 1234 | john |
| 1 | 2 | 2 | title2 | task 1.2 | 3456 | john |

LEFT JOIN 3 columns to get username

I have three columns I need to join which comes from 3 different tables,
Contributions table:
+-----------+---------------------+
| record_id | contributor_user_id |
+-----------+---------------------+
| 1 | 2 |
+-----------+---------------------+
| 1 | 5 |
+-----------+---------------------+
Members table:
+--------------+---------+
| username | user_id |
+--------------+---------+
| Test | 1 |
+--------------+---------+
| Test2 | 5 |
+--------------+---------+
| Test3 | 6 |
+--------------+---------+
Records table:
+---------+-----------+
| user_id | record_id |
+---------+-----------+
| 28 | 1 |
+---------+-----------+
For what I need to return is the username and user_id for displaying the record owner. Also, display the username and the user_id, but this can be multiple (more than 1+ user). I've tried this:
SELECT usr.username,
usr.user_id,
rec.record_id,
contrib.record_id,
contrib.contributor_user_id
FROM
(
records rec
INNER JOIN members usr ON rec.user_id = usr.user_id
# this returns records as NULL
LEFT OUTER JOIN contributions contrib ON rec.record_id = contrib.record_id AND contrib.contributor_user_id = usr.user_id
# this works, but I need the username to be displayed too
LEFT OUTER JOIN contributions contrib ON rec.record_id = contrib.record_id
)
WHERE rec.record_id = 1
Try nesting the join for contributing users inside of the left join to contributions.
SELECT u.username, u.user_id, r.record_id, u2.username as ContributorName, u2.user_id as ContributorId
FROM records r
INNER JOIN members u
ON r.user_id = u.user_id
LEFT JOIN contributions c
INNER JOIN members u2
ON c.contributor_user_id = u2.user_id
ON r.record_id = c.record_id
WHERE r.record_id = 1
SELECT
usr.username AS record_owner
, usr.user_id AS record_owner_id
, rec.record_id
, con.contributor_user_id AS contributor_id
, contributors.username AS contributor_name
FROM
records rec
INNER JOIN
members usr
ON rec.user_id = usr.user_id
LEFT OUTER JOIN
contributions con
ON rec.record_id = con.record_id
INNER JOIN
members contributors
ON con.contributor_user_id = contributors.user_id
WHERE
rec.record_id = 1