want to understand how update works in mysql - mysql

New to mysql need help to understand this
SELECT * FROM roles1 r1 ;
result
id role
1 ROLE_SELLER1
1 ROLE_SELLER2
1 ROLE_SELLER3
2 ROLE_SELLER4
2 ROLE_SELLER5
SELECT * FROM roles r1 ;
result
id role
1 ROLE_SELLER1
2 ROLE_SELLER4
UPDATE roles1 r1 ,roles r SET r.role=r1.role WHERE r.id=r1.id ;
after the above update query roles table does not change at all.i thought it should be like
SELECT * FROM roles r1 ;
result
id role
1 ROLE_SELLER3
2 ROLE_SELLER5
SELECT r.,r1. FROM roles r RIGHT JOIN roles1 r1 ON r.id = r1.id;
result
id role id role
1 ROLE_SELLER1 1 ROLE_SELLER1
1 ROLE_SELLER1 1 ROLE_SELLER2
1 ROLE_SELLER1 1 ROLE_SELLER3
2 ROLE_SELLER4 2 ROLE_SELLER4
2 ROLE_SELLER4 2 ROLE_SELLER5
update roles r join roles r1 on r.id = r1.id set r.role = r1.role;
i thought when i use this it should update roles table like
result
id role
1 ROLE_SELLER3 (last matched value from roles1 table id 1)
2 ROLE_SELLER5(last matched value from roles1 table id 1)
Thanks in adv...

While I cannot really answer your question because I cannot understand it I can share with you a few things that might help clarify your understanding:
1. For any query, whether it is an update or select you will almost never do the following:
select * from table1, table2 ....
update * from table1, table2 ....
The reason why you'll never do that is because joining tables with just a comma does a full cross join every row to every row. It results not only in craziness, but way too much craziness. So just avoid such things. About the only time it's ever used is when you're joining a table with a single row and value...like a business_date...or some other single value table.
Instead you should use the following pattern for all joins:
select *
from table1 t1
join table2 t2 on t1.id = t2.id
...
Using the above pattern avoids full joins and all the ridiculousness that goes with them. You should always join on something, remember the key word on. You want to always be specifying how tables should relate to each other in all queries - updates,deletes,selects. Remember this it is very key.
2. Avoid id columns that aren't unique. I really shouldn't see tables with id's in them where the ids are not unique. Add a unique key to your table or make it the primary key and then you won't end up with duplicate id confusion.
Now on to your particular query, I'm going to take a total stab here since again your questions verbiage is difficult to parse made more-so by the values you provide. I'm going to assume you want the values of table 2 to update the values of table 1.
In other words table1 currently looks like:
id role
1 ROLE_SELLER1
1 ROLE_SELLER2
1 ROLE_SELLER3
2 ROLE_SELLER4
2 ROLE_SELLER5
and after the update you're going to want to see it look like the following because it will have taken the values of table2 and matched them to table1:
id role
1 ROLE_SELLER1
1 ROLE_SELLER1
1 ROLE_SELLER1
2 ROLE_SELLER4
2 ROLE_SELLER4
The update statement for such a transformation would look like this:
update roles r
join roles r1 on r.id = r1.id
set r.role = r1.role;
Anyway I'm not sure why professors at University teach joins with commas....but don't do it and you'll be a master of SQL in no time. Good luck!

Related

Adding Default Values on Joining Tables

I have the following tables:
Users
user_id course_id completion_rate
1 2 0.4
1 23 0.6
1 49 0.5
... ... ...
Courses
course_id title
1 Intro to Python
2 Intro to R
... ...
70 Intro to Flask
Each entry in the user table represents a course that the user took. However, it is rare that users have taken every course.
What I need is a result set with user_id, course_id, completion_rate. In the case that the user has taken the course, the existing completion_rate should be used, but if not then the completion_rate should be set to 0. That is, there would be 70 rows for each user_id, one for each course.
I don't have a lot of experience with SQL, and I'm not sure where to start. Would it be easier to do this in something like R?
Thank you.
You should first cross join the courses with distinct users. Then left join on this to get the desired result. If the user hasn't taken a course the completion_rate would be null and we use coalesce to default a 0.
select c.course_id,cu.user_id,coalesce(u.completion_rate,0) as completion_rate
from courses c
cross join (select distinct user_id from users) cu
left join users u on u.course_id=c.course_id and cu.user_id=u.user_id
Step1: Take the distinct client_id from client_data (abc) and do 1 on 1 merge with the course data (abc1) . 1 on 1 merge helps up write all the courses against each client_id
Step2: Merge the above dataset with the client info on client_id as well as course
create table ans as
select p.*,case when q.completion_rate is not null then q.completion_rate else 0
end as completion_rate
from
(
select a.client_id,b.course from
(select distinct client_id from abc) a
left join
abc1 b
on 1=1
) p
left join
abc q
on p.client_id = q.client_id and p.course = q.course
order by client_id,course;
Let me know in case of any queries.

Insert one db's different tables data to other db's single table

i'm running into a complex problem, the data in a db has three tables.
First_DB
-- default_users
id username email password
1 Timbog Timbog#mail.com vads7y3kkjdfa
2 Marta Marta#mail.com vads7y3kkjdfa
-- default_album
album_id album_name default_user_id
1 Name_Tim 1
3 Katarina 2
-- default_album_img
img_id image_file album_id
3 1320229733.jpg 1
4 3320229733.jpg 3
Second_DB
--users
user_id user_name user_email user_pass user_image
1 Timbog Timbog#mail.com vads7y3kkjdfa 1320229733.jpg
2 Marta Marta#mail.com vads7y3kkjdfa 3320229733.jpg
The approach i used to solve this problem is to first fetch all data by inner join, should i use full outer join and insert the required field to my table, the following query is actual by which i'm trying to make it wor:
INSERT INTO bbpin.users ( user_name, user_pin, user_email, user_password, user_img)
SELECT default_users.username, default_users.bb_pin, default_users.email, default_users.password
FROM bbmpins_pins.default_users
INNER JOIN bbmpins_pins.default_album_images
ON default_album_images.album_id = default_users.id;
i miss the thing how do i compare two table's id in this join maybe? or this query is all wrong by approach?
By two tables which are sepearte in First_DB there could be multiple record how do we trunk them to last entry only ?
Thanks
It looks like you are attempting to retrieve all rows from the default_users table. And along with each row, also return the corresponding row(s) from default_album table. And along with that, the corresponding row(s) from default_album_img table.
Given the example data, a query using inner joins would return the specified result:
SELECT u.id AS user_id
, u.username AS user_name
, u.email AS user_email
, u.password AS user_pass
, i.image_file AS user_image
FROM default_users u
JOIN default_album a
ON a.default_user_id = u.id
JOIN default_album_img i
ON i.album_id = a.album_id
That query will work for the example data.
But, if there is a row in default_user which doesn't have a matching row in default_album, then an inner join won't return that row:
-- default_users
id username email password
3 branstark bran#winterfell warg2
Or, if there are two or more rows in default_album that match a given user, then the query will return two copies of the row from default_user...
-- default_album
album_id album_name default_user_id
1 Tim2 1
Without a specification of what is to be returned in those cases, we can't recommend a query.
I don't see anything wrong with your current approach using a JOIN but could modify it a bit to be more readable and also you will have to join the relation table
INSERT INTO bbpin.users (user_id, user_name, user_pin, user_email, user_password, user_img)
SELECT du.id,
du.username,
du.bb_pin,
du.email,
du.password,
dai.image_file
FROM bbmpins_pins.default_users du
JOIN bbmpins_pins.default_album da ON du.id = da.default_user_id
INNER JOIN bbmpins_pins.default_album_images dai
ON dai.album_id = da.album_id;

Join table on pattern match

I have been struggling with this for several hours, so any feedback or advise is very welcome.
I have three tables:
users
id name email
1 test test#test.com
2 test2 test2#test.com
pets
pet_id pet_name user_id
1 sam 2
2 sally 1
transactions
trans_id custom
1 1
2 pid2
3 pid1
OK, what I would like to do is get transaction data relating to the user. So in the 'transactions' table 'custom' value 1 would relate to 'users' with the id. Thats the simple bit...
'Transactions' with 'pid' relate to the pets id, so 'pid2' relates to sally, whose user is user id 1. So I need to join the transaction table when custom relates to the user id or if its prefixed with 'pid' and the appending value relates to the 'pet_id'.
Here's an example of the result I would like:
Transactions relating to user_id 1:
trans_id 1, custom 1
trans_id 2 custom pid2 (this is because the pets owner is user_id 1)
Here is where I am with my attempt at the moment:
SELECT users.*, transactions.*
FROM users
LEFT JOIN transactions on users.id = transactions.custom
This is where I'm falling over:
SELECT users.*, transactions.*
FROM users
LEFT JOIN pets ON pets.user_id = user.id
LEFT JOIN transactions on (users.id = transactions.custom
OR pets.pet_id REGEXP '^pid(transactions.custom)')
If you can't change the table design and the prefix pid is fixed you could use
OR (
pets.pet_id = SUBSTR(transactions.custom, 3)
AND SUBSTR(transactions.custom, 1 FOR 3) = 'pid')
see documentation to SUBSTR and because MySQL automatically converts numbers to strings as necessary, and vice versa, see: http://dev.mysql.com/doc/refman/5.7/en/type-conversion.html
You HAVE to refactor Your DB. Current structure will guarantee of speed problems.
Table transactions should looks like
CREATE TABLE transactions
(
id Int NOT NULL, (id of transaction)
pet_id Int, (can be null)
user_id Int (can be null)
other columns here...
)
;

MySQL: Join based on multiple columns

I need to join table_1 and table_2 in MySQL and compare which user has the most winnings. Then update table_2.winner with the user id which has won..
table 1
city user winnings
1 a 99
1 b 0
1 c 50
1 d 2
table 2
city user_1 user_2 winner
1 a b a
1 c d 50
However I'm struggling to figure out how to join the tables thus far I have
SELECT table_1.winnings AS win_a, table_1.winnings AS win_b
FROM table_1, table_2
WHERE table_2.user_1 = table_1.user
AND table_2.user_2 = table_1.user
http://sqlfiddle.com/#!2/c855b/1
You can join against the table multiple times like this:
SELECT IF(user1.winnings > user2.winnings, "user1", "user2")
FROM table_2 games
JOIN table_1 user1 ON games.user_1 = user1.user
JOIN table_1 user2 ON games.user_2 = user2.user
http://sqlfiddle.com/#!2/c855b/16
I just used #skishore's query, a bit fixed, because it is broken for draws. The one that takes draws under consideration would be
SELECT
case when user1.winnings > user2.winnings then user1.user
when user2.winnings > user1.winnings then user2.user
else null
end
FROM table_2 games
JOIN table_1 user1 ON games.user_1 = user1.user
JOIN table_1 user2 ON games.user_2 = user2.user
But apart from this, I still don't get the purpose. I wrote this in comment to #skishore answer, but paste it here also. Consider the case:
User c won 99 matches played with user b, user d on the other hand won 2 matches played with user c. But who will be the winner between c and d? C
The second question is - why do you need this stored in a separate table? Winnings number will be dynamically changing so you would have to create trigger to keep winner column on table2 up to date. Can't you just get winner using this query?

MySQL Left Join with multiple rows

I'm looking to join a 2 tables but the second table has a one to many relation. Can I omit the entire row if any of the lines have a certain value? Let me explain more.
User table
id name email
1 bob bob#test.com
2 foo foo#test.com
Music table
id userId
1 1
1 2
2 1
3 1
2 2
Say I don't want it to show the user if he has a relation to music table id 2. Also looking for distinct user.
If I try something like this it will still show both users.
SELECT * FROM users u LEFT JOIN music m ON u.id = m.userId WHERE m.id <> 3
I want it to check all the rows and if it has the id 3, it won't show. I hope I made sense. Thanks a lot.
Try using sub query like this:
SELECT * FROM users
WHERE id NOT IN (SELECT userId FROM music WHERE id=3)
This query means to select all users if their id is not related with music.id 3.