I have two table client and cash.
Table client:
ID Name ... other data
------------------------
1 Bob
2 Marry
3 Tom
Table cash:
ID Cash Id_client_fk
----------------------
1 500 1
2 500 3
3 500 3
4 500 1
I want to sum cash from every client, even if not exist in table cash.
The foreign key is id_client_fk to table client -> ID
You could use SUM() and a left join to achive this:
SELECT u.ID, u.Name, SUM(c.Cash) cash FROM client u
LEFT JOIN cash c ON c.Id_client_fk = u.ID
GROUP BY u.ID
To remove the NULL values you could use an IF statement:
SELECT u.ID, u.Name, SUM(IF(c.Cash > 0, c.Cash, 0)) cash FROM client u
LEFT JOIN cash c ON c.Id_client_fk = u.ID
GROUP BY u.ID
Not quite clear it. Please bring examples of data and what result you want. for example, just a few lines to understand the idea.
If I understand correctly, you need something like this:
SELECT client.id,client.name,s.sum_c FROM client INNER JOIN (SELECT `id_client_fk`, sum(`cash_row`) sum_c FROM `cash` GROUP BY `id_client_fk`) s ON client.id=s.id_client_fk ORDER BY 3 desc limit 20;
Related
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`)
)
)
I have tables shown below:
users table
user_id user_email user_name
1 a#a.com a
2 b#b.com b
3 c#c.com c
bookmarks table
bookmark_id user_id bookmark_url
1 1 http://aaa.com
2 3 http://bbb.com
3 3 http://ccc.com
4 3 http://ddd.com
comments table
comment_id user_id content
1 2 'hello'
2 2 'hello2'
What I want to get is like this :
user_id user_email user_name bookmarksCount commentsCount
1 a#a.com a 1 0
2 b#b.com b 0 2
3 c#c.com c 3 0
From above, each xxx_id is auto incremented sequence id.
I think to get above result, I have to join these 3 tables.But, if there is no match user_id in bookmarks and comments table, they can't be joined. But I have to get result with 0 if there is no match.
Is it possible to join these tables to get result even though there is no match column?
You can just use correlated subqueries:
select u.*,
(select count(*) from bookmarks bm where bm.user_id = u.user_id
) as cnt_bookmarks,
(select count(*) from comments c where c.user_id = u.user_id
) as cnt_comments
from users u;
If you attempt to do this using join, you will have problems, because you will generate a Cartesian product of bookmarks and comments for each user. In addition, doing the aggregation after the join is likely to incur performance problems, because the data for the aggregation will be larger than necessary.
For this query, indexes on bookmarks(user_id) and comments(user_id) should provide very good performance.
Okay, so I have two tables that I need to link together with a JOIN query. There is a table called likes and a table called users. The users table looks something like this
id name
----- ------
1 Mark
2 Mike
3 Paul
4 Dave
5 Chris
6 John
The likes table looks like this.
user_one user_two match_id
----- ------ --------
1 2 abc
2 1
1 3 acc
3 1 abb
1 5 aee
5 1
The expected result should be
id name
----- ------
1 Mark
The two tables should only be linked on the rows in the likes table where the users_one column is set to the value that is most commonly found in that column. In this case, the user with the id of 1 is in the likes table with the user_one column 3 times where the match_id isn't empty.
I've thought it out to be written something like this
SELECT users.*, likes.COUNT(*) AS count
FROM users
JOIN likes
ON users.id = likes.user_one
WHERE likes.match_id != ''
But, I know this isn't correct. Is there a way to link two tables with a JOIN only on the most common rows in one of the tables?
Would Grouping work for what you need... ?
SELECT users.id, users.name, count(*) AS count
FROM users
JOIN likes
ON users.id = likes.user_one
WHERE likes.match_id != ''
group by users.id, users.name
should give you something like
1 Mark 3
Should be something like this, if I understood the question
select top 1 user_one, name
from likes
inner join users ON users.id = likes.user_one
where match_id != ''
group by user_one
order by count(*) Desc
Are you looking for something like this?
select u.id, u.name, count(*)
from users u
inner join likes l
on l.id = l.user_one and l.match_id != ''
group by u.id, u.name
order by count(*) desc
limit 1
The limit 1, combined with sorting by the # of likes in descending order will result in getting one user - the one with the most matched likes.
Try:
select *
from users
where id in (
select id
from likes
group by id
order by count(*) desc, id
limit 1
)
The subquery returns the id of the row with the most appearances in the likes table (group by id and order by count(*) desc). I've added id to the order by to give predictable results in case there are multiple with the same number of appearances. This is used to join to the users table to give the resultset required.
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?
I have table users and another table premium_users in which I hold the userid and the date when he bought premium membership.
How can I use mysql join , so that in a single query I can select all the columns from the table users and also know for each premium user the date he joined on.
USERS:
ID USERNAME
1 JOHN
2 BILL
3 JOE
4 KENNY
PREMIUM USERS:
ID USERID DATE
1 2 20/05/2010
2 4 21/06/2011
And the final table (the one that will be returned my the query) should look like this:
ID USERNAME DATE
1 JOHN
2 BILL 20/05/2010
3 JOE
4 KENNY 21/06/2011
Is it ok for some rows to have the DATE value empty?
How can I check if that value is empty? $row['date']=='' ?
EDIT:
This was only an example, but the users table has much more columns, how can I select all from users and only date from premium_users without writing all the columns?
select u.*, pu.DATE
from USERS u LEFT OUTER JOIN PREMIUM_USERS pu on
u.ID = pu.USERID
You can check if a row is empty with:
if (!$row['DATE'])
{
...
}
select USERS.ID, USERS.USERNAME, PREMIUM_USERS.DATE
from USERS
join PREMIUM_USERS on USERS.ID = PREMIUM_USERS.ID
order by USERS.ID
This is mssql syntax, but it should be pretty similar...
select *
from users u
left join premiumUsers p
on u.id = p.id
order by u.id asc
SELECT A.*, B.DATE
FROM USERS A
LEFT JOIN PREMIUIM_USERS B on A.ID=B.USERID
EDITED
It might be easier to have it all in one table. You can have nullable fields for isPremium(t/f) and premiumDate. you actually dont even need the isPremium field. just premiumDate if its null they are not premium and if it has value they are premium user and you have the date they joined.