mysql SELECT query with left join is not producing the result I am expecting.
I hope someone can show me or point me to the right direction,
I am trying to build a query where I get all the users name from the "users" table and
fetch the sum of all the time they spent for a particular date from the master table. I've used the left join but I am not getting the result as expected.
SUM(m.time_spent) as sum_total_time
FROM master as m
LEFT OUTER JOIN users as u ON u.user_id = m.user_id
WHERE m.date_created >= '2016-05-09'
AND m.date_created <= '2016-05-13'
GROUP BY name
ORDER BY name
master table
master_id user_id time_spent date_created
1 1 40 2016-05-01
2 2 36 2016-05-02
3 3 56 2016-05-03
4 2 33 2016-05-03
5 1 32 2016-05-05
nth nth nth number nth date
users table
user_id first_name last_name
1 James Green
2 Robert Cox
3 Andy Roger
etc etc etc
I want the output result should look like this:
user_id Name sum_total_time
1 James Green 62
2 Robert Cox 69
3 Andy Roger 56
4 Brian Harper 0
5 Angel Lee 0
6 Andrew Martin 55
.....
.....
Nth Name Nth value
You have to select data directly from the master table, group by user and calculate the sum. Then you can join this result with the user table to get all the information about the user.
Could be date conversione issue ..
SUM(m.time_spent) as sum_total_time
FROM master as m
LEFT OUTER JOIN users as u ON u.user_id = m.user_id
WHERE m.date_created >=STR_TO_DATE( '2016-05-09', '%Y-%m-%d)
and/or you have also incomplete sql
SUM(m.time_spent) as sum_total_time
FROM master as m
LEFT OUTER JOIN users as u ON u.user_id = m.user_id
WHERE m.date_created >= '2016-05-09'
AND m.date_created // this condition don't match with nothing..
// could be you forgot a part
Update 1
If you want user totale then
select u.id, u.name, SUM(m.time_spent) as sum_total_time
FROM master as m
Inner JOIN users as u ON u.user_id = m.user_id
WHERE m.date_created >=STR_TO_DATE( '2016-05-09', '%Y-%m-%d)
AND m.date_created <= =STR_TO_DATE('2016-05-13'', '%Y-%m-%d)
Group by u.id
Related
I have this arrangement:
I want to retrieve all the posts shared by followeds, bearing in mind those shared posts doesnt belong to another followeds or the main follower.
TABLE USERS
id_user | name
15 Joe
16 Dan
17 Tom
TABLE COMMUNITY
id_follower | followed
15 16
15 17
TABLE POSTS
id_post | id_user | post
1 15 hi1
2 16 hi2
3 15 hi3
4 17 hi4
5 15 hi5
6 16 hi6
7 17 hi7
8 18 hi8
9 14 hi9
I'm adding up a new table "shares".
TABLE SHARES
id_sharer | id_post
16 4
14 8
17 8
16 9
EXPECTED OUTPUT POSTS
17 8 hi7 (shared by Tom)
16 9 hi6 (shared by Dan)
How shouldit be the sql query to get this new arrangement?
I was thinking adding a line LEFT JOIN shares l ON l.id_sharer=p.id_user
SELECT p.*,
FROM posts p
LEFT JOIN users u ON u.id_user=c.id_followed
LEFT JOIN shares l ON l.id_sharer=c.id_followed
LEFT JOIN community c ON c.id_follower=p.id_user
WHERE p.id_user=15
ORDER BY p.date_post DESC
*Tested but not retrieve as expected
Here is a first crack at this for you:
SELECT p.id_post, p.id_user, p.post, IF(l.date_like IS NOT NULL, l.date_like, p.date_post) AS date, l.id_liker
FROM posts p
LEFT JOIN likes l ON l.id_post = p.id_post
LEFT JOIN users u ON u.id_user = l.id_liker
ORDER BY l.date_like DESC
GROUP BY p.id_post
As a quick walk through of how I am approaching the problem, first I am LEFT JOINing the likes and ordering them in descending order, just as you did. Then I am grouping on the post id in order to ensure I only get one line per post. Then in the selector I am checking to see if the like date is null and substituting in the date of the post instead of the most recent like if there are no likes.
UPDATE
This should add the logic to ensure that only the likes of followers will count. Since one probably cannot follow themselves this should also keep one's own likes from affecting position.
SELECT p.id_post, p.id_user, p.post, IF(l.date_like IS NOT NULL, l.date_like, p.date_post) AS date, l.id_liker
FROM posts p
LEFT JOIN likes l ON l.id_post = p.id_post
LEFT JOIN users u ON u.id_user = l.id_liker
LEFT JOIN community c ON l.id_liker = c.followed
WHERE c.id_follower = 15
ORDER BY l.date_like DESC, p.date_post DESC
GROUP BY p.id_post
I understand that 'TABLE POSTS'.'id_user' is the author of the post and matches to 'TABLE USERS'.'id_user' and that you want to see the Posts that have Entries in 'TABLE LIKES' first and then all the others.
So I suggest to the following JOIN and ORDER BY
select p.*, l.date_like, u.* from posts p
left join likes l on p.id_post=l.id_post
left join users u on l.id_liker=u.id_user
order by l.date_like desc, p.date_post desc
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 3 tables:
users:
id name
1 Jack
2 Vasya
3 John
4 Robert
5 Dmitry
6 Dylan
cities:
id city
1 London
2 Kyiv
3 New-York
4 Chicago
5 Moscow
6 Dubai
users_cities:
user_id city_id
1 1
3 1
5 6
2 3
4 5
6 6
I need to select users with Jack in London by Jack's id(users.id = 1) or users in Dubai with Dmitry(users.id = 5) using JOIN.
How could I do it?
What I have tried:
SELECT `u`.`username`, `uc`.`city_id` FROM `users` as `u`
INNER JOIN `users_cities` as `uc` ON `u`.`id` = `uc`.`user_id`
INNER JOIN `users_cities` as `uc1` ON `uc1`.`city_id` = `uc`.`city_id`
WHERE `u`.`id` = 1
It returns:
username city_id
Jack 1
Jack 1
You're so very close. You only need to JOIN to user_cities once for your query. Then use the WHERE clause to determine the users or cities you wish to filter on.
If you want the city name in the result set then make an additional join from user_cities to cities.
As you are joining twice on the same result set (user_cities) you are effectively querying that result twice, which is why you are getting duplicate 'Jacks'.
If this is not exactly what you need, then adjust your WHERE clause to determine how you would like to filter the result set.
SELECT
u.username,
c.city
FROM
users as u
INNER JOIN users_cities as uc ON u.id = uc.user_id
INNER JOIN cities as c ON uc.city_id = c.id
WHERE
u.id = 1 -- Jack
OR u.id = 5 -- Dimitry
I've got the following tables:
Articles:
Nr Name Price
1011 DU 10
1012 DA 5
1013 DO 20
Clients
Nr Name Street Zip
123 John ... ...
234 Will ... ...
Orders
Nr Client_Nr Art_Nr Quantity
1 123 1011 1
2 123 1012 2
3 234 1012 2
4 234 1013 5
To know the total sum of orders per customer,
I use the following statement:
SELECT Clients.Name,
SUM(Orders.Quantity * Article.Price) AS "Total"
FROM Orders
LEFT OUTER JOIN Articles
ON Orders.Art_Nr = Articles.Nr
LEFT OUTER JOIN Clients
ON Orders.Client_Nr = Clients.Nr
GROUP BY Clients.Name;
Is left outer joins used when there are rows in one table that may not be referenced in the second table.
What is the better way of writing the above query?
Can I do this:
SELECT clients.name, SUM(orders.quantity * articles.price)
FROM orders
INNER JOIN articles ON orders.art_nr = articles.nr
INNER JOIN clients ON orders.client_nr = clients.nr
GROUP BY clients.name;
I have a hypothetical table "users" with the columns
user_id (auto incremented)
name
foo
bar
last_updated
This table is updated multiple times per day. How can I query to get the last update, per user, per day, going back X days?
Example Data
1 John a b "2013-01-31 02:01:12"
2 Rich c d "2013-01-31 22:41:12"
3 John e f "2013-01-31 22:01:15"
4 Rich g h "2013-02-01 16:01:12"
5 John i j "2013-02-01 22:21:12"
6 Rich k m "2013-02-01 22:21:12"
Desired Return Set:
2 Rich c d 2013-01-31
3 John e f 2013-01-31
5 John i j 2013-02-01
6 Rich k m 2013-02-01
I am able to get the last updated per user overall with the following query, it's applying it to each day that I am struggling with.
SELECT u1.*
FROM users u1
LEFT JOIN users u2
ON (u1.name = u2.name AND u1.user_id < u2.user_id)
WHERE u2.user_id IS NULL
First of all the table name users is very confusing, since these aren't the users but the logins.
Beyond that you're on the right way. You just need to add a comparison on the date in the join.
SELECT u1.*
FROM users u1
LEFT JOIN users u2
ON (u1.name = u2.name AND date_format(u1.last_updated, '%Y-%m-%d') = date_format(u2.last_updated, '%Y-%m-%d') AND u1.user_id < u2.user_id)
WHERE u2.user_id IS NULL
See it work in this SQL fiddle.
Do this by summarizing the data at the date level and then joining back:
select u.*
from users u join
(select u.nanme, DATE(last_updated) as thedate, MAX(last_updated) as maxlastupdated
from users u
group by u.name, DATE(last_updated)
) usum
on u.name = usum.name and
u.last_updated = usum.maxlastupdated