how to use count in MySQL in good properly way - mysql

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;

Related

SQL how do I sum up a has many relationship

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.

Why MySQL gives me some result in aggregate function without group by statement

i've experienced something... weird? using an aggregate function WITHOUT group by statement (yes, i know i sould). I'm using mysql 5.5 in this moment.
I've use some example tables with the same structure as in my real situation, so example may be extrange, sorry.
Let's explain.
I have three tables with some referencial integrity:
As you can imagine: both, parent, child and person, are FK from Persons table id.
- Persons -
id name
1 Anna
2 Ben
3 Charly
4 Dennis
5 Emma
6 Fiona
- Relationships -
parent child
1 3
1 4
2 5
- Log -
person date
1 2020-05-05
Anna has two childs, Charly and Dennis
Ben has one, Emma
Fiona hasn't
Only Anna has an entry on log table
Let's party.
Find children id 3 name ONLY if number 6 is his parent (looking for Charly if is Fiona's son)
select P.name, R.child, R.parent
from Persons P
join Relationships R on P.id = R.child
left join Log L on L.person = P.id
where R.parent = 1
and R.child = 3
No result shown, ok, that's what i expected because as we can see, there's no row that matches condition.
Adding an aggregate function and group by shows the same 0 results.
select P.name, R.child, R.parent, count(L.person) as N_Entries
from Persons P
join Relationships R on P.id = R.child
left join Log on L.person = P.id
where R.parent = 1
and R.child = 3
group by P.id
BUT
if i remove the group by condition i expect the same result
if there're no result, then grouping should be unnecesary.
select P.name, R.child, R.parent, count(L.person) as N_Entries
from Persons P
join Relationships R on P.id = R.child
left join Log on L.person = P.id
where R.parent = 1
and R.child = 3
name child parent N_Entries
Charly null null 0
Why does it returns something?
Thank you and sorry about my bad english.

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 select 4 tables with 3 count

I have four tables
users
ID display_name
1 Name1
2 Name2
3 Name3
A user can add books to table books
books
book_id AddedByuserID
1 1
2 1
3 2
4 3
Also a user can add ebooks to table ebooks
ebooks
ebook_id AddedByuserID
1 1
2 2
3 2
4 3
Now a user can add books only to his collection (not ebooks)
collection
userID book_id
1 1
1 2
1 3
I need an output like this:
display_name books_added ebooks_added books_in_collection
Name1 2 1 3
Name2 1 2 2
Name3 1 1 1
This is what got:
SELECT users.*, COUNT(DISTINCT collection.book_id) AS books_in_collection, COUNT(DISTINCT books.AddedByuserID) AS books_added, COUNT(DISTINCT ebooks.AddedByuserID) AS ebooks_added
FROM users LEFT JOIN collection ON users.ID = collection.userID
LEFT JOIN books ON users.ID = books.AddedByuserID
LEFT JOIN ebooks ON users.ID = ebooks.AddedByuserID
GROUP BY users.ID
ORDER BY display_name ASC
The user display_name gets displayed correct and also the collection count, but the two other counts are showing 1.
If I remove DISTINCT the collection count says 86, and the two other counts show nothing.
I try to understand LEFT join and read tutorials but i'm stuck at the moment.
I would suggest correlated subqueries:
select u.*,
(select count(*) from collection c where u.id = c.userId) as books_in_collection,
(select count(*) from books b where u.id = b.AddedByUserId) as books_added,
(select count(*) from ebooks e where u.id = e.AddedByUserId) as ebooks_added
from users u;
I don't know why you are filtering out the third user, however.

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?