SQL how do I sum up a has many relationship - mysql

So I have the following table, I managed to join users and membership tables just fine with a left join however I've been unsuccessful at summing up the individual customers' total.
Here's my code, the one-to-one associations seem to be doing fine however the summing up of the total seems to not display, what am I doing wrong? is there a different way of summing up a one-to-many association?
SELECT name, membership.userId as customerId, SUM(sales.total) as Total
FROM users
LEFT OUTER JOIN membership ON membership.userId = users.id
LEFT OUTER JOIN sales ON buyerId = users.id
Tables
Users table:
id name type
1 John Customer
2 Adam Customer
3 Robert Customer
Membership table:
id userId
1 1
2 2
3 3
Sales table:
buyerId total
1 12
1 20
1 5
2 5
2 10
3 5
3 5
Desired output:
Sales Report:
Name CustomerId Total
John 1 37
Adam 2 15
Robert 3 10

SELECT name, membership.userId as customerId, SUM(sales.total) as Total
FROM users
LEFT OUTER JOIN membership ON membership.userId = users.id
LEFT OUTER JOIN sales ON buyerId = users.id
GROUP BY name, customerId
You need to group by user.

Related

how to use count in MySQL in good properly way

I have 2 tables, this is my fiddle http://sqlfiddle.com/#!9/da5e4e/3
so basically i have 2 tables called personal and interview_score with personal.id = interview_score.personal_id.
assume this is my personal table
id name
1 John Doe
2 Nian
3 Rijali
and this is my interview_score table
id personal_id aspect_id
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
on this case, i just want to count how many personal_id in my interview_score table with this query
SELECT COUNT(i.id) as interviewed FROM personal p LEFT JOIN interview_score i ON i.personal_id = p.id GROUP BY i.personal_id;
but it returns just like this
interviewed
0
3
2
meanwhile, my expected result is just like this
interviewed
2
because on that table there are 2 personal_id based on that condition.
where my wrong at?
You can use join instead of left join also you need to group by p.id
SELECT COUNT(i.id) as interviewed FROM personal p JOIN interview_score i ON i.personal_id = p.id GROUP BY p.id;
from the above query you can get the count
To get count for a particular person
SELECT COUNT(i.id) as interviewed FROM personal p JOIN interview_score i ON i.personal_id = p.id and p.id=1 GROUP BY p.id;

MySQL join query on 3 tables [duplicate]

This question already has answers here:
Inner join with count() on three tables
(6 answers)
Closed 4 years ago.
user table:
id groupid username
1 1 user1
2 1 user2
3 2 user3
4 2 user4
group table:
id groupname
1 group1
2 group2
3 group3
sales table:
id userid amount
1 1 10
2 1 15
3 1 30
4 3 10
5 3 25
I like to know how many rows in sales table by groupid, not by userid. But sales table has no groupid field.
How can I join these 3 tables to get what I want? is this possible with one join query?
User INNER JOIN between the three tables based on the (foreign) key relationship between them, and use WHERE condition of groupid, to get results only for a specific $groupid
SELECT sales.* FROM sales
INNER JOIN user ON user.id = sales.userid
INNER JOIN group ON group.id = user.groupid
WHERE group.id = $groupid;
EDIT:
As asked further in the comments, to get Sum of sales for a particular groupid, we use SUM function. Here is the updated query:
SELECT SUM(sales.amount) AS total_sales FROM sales
INNER JOIN user ON user.id = sales.userid
INNER JOIN group ON group.id = user.groupid
WHERE group.id = $groupid;
You can just join two tables to get what you want:
select u.groupid, count(*) as count, sum(s.amount) as total
from user u
join sales s on s.userid = u.id
group by u.groupid;

How to get different results from one mysql table?

I have a user table in the database where all users of the system are stored.
The table has a user_id and a business_name and a first_name.
Some users are merchants and get a business name,
some users are consumers and get a first name.
In a second table I have transactions with a user_id and a merchant_id (which are defining the transaction) and an amount. Both ids reference to user table.
Table users:
user_id bus_name first_name role_id
1 Thomas 10
2 comp1 7
3 Peter 10
4 comp2 7
(role_id is defining with 10=consumer, 7=merchant)
Table transactions:
trans_id amount user_id merchant_id
1 12 1 2
2 23 3 2
3 34 3 4
4 19 1 4
Now I want to have a query with a result as one table:
This table should contain the transaction with amount, user_id, first_name, merchant_id and bus_name.
I want to get this result:
trans_id amount user_id first_name merchant_id bus_name
1 12 1 Thomas 2 comp1
2 23 3 Peter 2 comp1
3 34 3 Peter 4 comp2
4 19 1 Thomas 4 comp2
I have the problem that either I get only the first_name and empty bus_name or I get only the bus_name but empty first_name.
I am using a left join:
...
left join `users`
on(
(`transactions`.`user_id` = `users`.`user_id`)
)
...
But for this I would get for user_id=1 the first_name=Thomas and the bus_name='' would be empty because I only reference to one line in table and not also to different user with user_id=2.
But I want to say something like:
for trans_id=1
get first_name FROM users WHERE transactions.user_id = users.user_id
AND
get bus_name FROM users WHERE transactions.merchant_id = users.user_id
Thanks for your help, I tried so many things but it does not work.
You have to join the user table twice:
SELECT t.*, u.first_name, m.bus_name
FROM transactions t
JOIN users as u
ON t.user_id = u.user_id
JOIN users as m
ON t.merchant_id = m.merchant_id
you could use a duoble join in users table
select a.trans_id, a.amount , a.user_id, b.first_name, a.merchant_id, c. bus_name
from transactions a
inner join users b on a.user_id = b.user_id and b.role_id = 10
inner join users c on a.merchant_id = c.user_id and c.role_id = 7
To join the user table twice worked fine. With "left join users as consumer" I create a kind of a virtual users table called "consumer", this one is joined. Of course in select I had to adjust table name as well. Same for second "virtual" table od users, called "merchant".
select
`transactions`.`trans_id` AS `trans_id`,
`transactions`.`merchant_id` AS `merchant_id`,
`merchant`.`bus_name` AS `bus_name`,
`transactions`.`user_id` AS `user_id`,
`consumer`.`first_name` AS `first_name`,
`cards`.`card_id` AS `card_id`,
`cards`.`serial_no` AS `serial_no`
from (
`transactions`
left join `cards`
on(
(`cards`.`card_id` = `transactions`.`card_id`)
)
left join `users` as consumer
on(
(`consumer`.`user_id` = `transactions`.`user_id`)
)
left join `users` as merchant
on(
(`merchant`.`user_id` = `transactions`.`merchant_id`)
)
)

Propel2; how to use querybuilder for subselect query

Problem:
I'm having trouble finding a solution building a query with QueryBuilder (perhaps getting it done with regular sql query first will help):
Trying to retrieve all customers for a user (has shop credits at one of the shops user is linked to), need the total credits (sum of credits at shops belonging to that user) as virtual column (to be able to order on), using paginate().
Database structure:
Table customers
id email other_fields
1 1#email.com f
2 2#email.com o
3 3#email.com o
Table users
id email other_fields
1 1#user.com b
2 2#user.com a
3 3#user.com r
Table shops
id name other_fields
1 Shop 1 m
2 Shop 1 o
3 Shop 1 o
Table user_shops
user_id shop_id
1 1
1 2
3 3
Table customer_shop_credits
customer_id shop_id credits
1 1 55
1 2 45
2 2 3
3 3 44
Expected result:
When retrieving customers for user 1, I'd expect to get back customer 1 with 100 credits and customer 2 with 3 credits
Closest I got:
$credits_query = CustomerShopCreditQuery::create()
->useShopQuery()
->useUserShopQuery()
->filterByUserId($user->getId())
->endUse()
->endUse()
;
$customers = CustomerQuery::create()
->addSelectQuery($credits_query, 'credits_alias', false)
->useCustomerShopCreditQuery()
->useShopQuery()
->useUserShopQuery()
->filterByUserId($user->getId())
->endUse()
->endUse()
->endUse()
->withColumn('sum(credits_alias.credits)', 'credits')
->groupById()
->orderBy($order_by_column, $direction)
->paginate($page, $page_size);
Which results in the following query:
SELECT customers.id, customers.email, sum(credits_alias.credits) AS credits
FROM customers
CROSS JOIN (
SELECT customer_shop_credits.id, customer_shop_credits.customer_id, customer_shop_credits.shop_id, customer_shop_credits.credits
FROM customer_shop_credits
INNER JOIN shops ON (customer_shop_credits.shop_id=shops.id)
INNER JOIN user_shops ON (shops.id=user_shops.shop_id)
WHERE user_shops.user_id=159
) AS credits_alias
INNER JOIN customer_shop_credits ON (customers.id=customer_shop_credits.customer_id)
INNER JOIN shops ON (customer_shop_credits.shop_id=shops.id)
INNER JOIN user_shops ON (shops.id=user_shops.shop_id)
WHERE user_shops.user_id=159
GROUP BY customers.id
ORDER BY customers.id DESC
LIMIT 25
But gives me results with wrong sum of credits.
Not to sure about the CROSS JOIN. When I edit this query and make it a JOIN and use ON (credits_alias.customer_id = customers.id) as a condition, the sum of credits is better, but seems to have the classic join problem of doubling the sum

MYSQL: Multiple Table Join - Conditional on previous join

MEMBERS_TABLE
member_id
---------------------------------------------
1
ACCOUNTS_TABLE
account_id member_id
---------------------------------------------
1 1
INVESTMENTS_TABLE
investment_id account_id
---------------------------------------------
1 1
2 1
FUNDS_TABLE
fund_id investment_id
---------------------------------------------
1 1
2 2
This is my current query:
SELECT
m.member_id,
a.account_id,
i.investment_id,
f.fund_id,
COUNT(a.account_id) AS member_accounts_total,
COUNT(i.investment_id) AS member_investments_total,
COUNT(f.fund_id) AS member_funds_total
FROM members AS m
LEFT JOIN accounts AS a ON m.member_id = a.member_id
LEFT JOIN investments AS i ON a.account_id = i.account_id
LEFT JOIN funds AS f ON f.fund_id = i.fund_id
I would like to see the following results:
member_accounts_total: 1
member_investments_total: 2
member_funds_total: 2
Instead, I am getting these results:
member_accounts_total: 2
member_investments_total: 2
member_funds_total: 2
I really don't want to write multiple queries for this.
Just need to change
COUNT(a.account_id) AS member_accounts_total,
to
COUNT( distinct a.account_id) AS member_accounts_total,
The reason you're getting 2 is because the left join on accounts to investments results in 2 records. To get a distinct count of members you need to add well... distinct.
Note you may have problems with the other totals as well (Distinct may be needed there as well in the long run...) say if a member had multiple accounts. you may get odd counts as well (if each account had the same investment... would you want to see the count only once or twice?