Join table on pattern match - mysql

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...
)
;

Related

How to find out results for not matching particular condition in SQL from multiple tables?

I have 3 tables :
Person table stores basic person wise details with ID as primary Key
This person can have relationships (father / mother etc), which are saved in Relationship table, however the users for them are created in Person table (e.g. ID = 2,3 in person table), This way we know that 2,3 are related to user 1 (carry).
We also have 3rd table - address, which store user ID wise addresses.(for both a user and his related persons, who are also users)
I want to find out if an address exists for either a user or for his related users in SQL. How to achieve this ?
You can combine two rules and search on the combined table as below
SELECT * FROM
(
SELECT username,id,Address.Address
FROM Person
INNER JOIN Address ON Person.id = Address.Userid
UNION ALL
SELECT username,id,Address.Address
FROM Person
INNER JOIN Relationship ON Relationship.Relatedid = Person.id
INNER JOIN Address ON Relationship.Userid = Address.Userid
) as RES
WHERE Address = 'xyz road'
Also you can find DBFiddle link to workout
Query:
select p.id,p.username,(case when a.userid is null then 'No' else 'Yes'end) IsAddressAvailable
from Person p
left join Address a on p.id=a.Userid
Output:
id
username
IsAddressAvailable
1
Carry
Yes
2
Carry-Father
No
3
Carry-Mother
Yes
db<fiddle here

want to understand how update works in 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!

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;

mysql query find sets which element match to another sets element

My tables are like below format
User table
> id username interest_ids
> 1 Ram 1,2,3
> 2 Suja 2,3,
> 3 Rahul 2,4,5,6
> 4 nipa 1,4,6
Interest Tables Like
id name
1 Music
2 Book
3 News
4 T.V watching
5 Song
6 Dancing
7 Game
now i want to search user who have same interest.
example Nipa is a user whose interest id are 1,4,6
and interest ids match with user Ram (id 1)and Rahul(id 3)
What is mysql query so i can fetch users who has similar interest id like nipa.
If your tables were normalised properly (WHICH THEY SHOULD BE! DO IT!) and you had a user_interests table that looked like this:
create table user_interests (
user_id integer,
interest_id integer
);
Then your answer would be:
select distinct username
from users u
inner join user_interests ui
on u.id = ui.user_id
where ui.interest_id in
(select ui2.interest_id
from users u2
inner join user_interests ui2
on u2.id = ui2.user_id
where u2.username = 'Nipa'
)
and u.user_name <> 'Nipa'
As it stands, mysql can't split strings without a lot of effort that would be better spent fixing the tables.
Here's an example

Selecting results from 2 tables based on the variables in 3th table

I have 2 tabes in my database:
users - userID(primary key), username, password
courses - id(primary key), name, text
subscriptions - id(primary key), curso_id, user_id
right in the subscription table I am writing the users UserID inside -> user_id with the id of the course for which he is subscribed curso_id so the results in the subscrption database are like
subscribtions table:
id user_id curso_id
1 12 1
2 5 1
3 12 2
4 6 7
this is the users table:
users table
userID username password
1 user1 passw1
2
3
4
and this is the courses table:
course table:
id course_name descriotion
1 course one text
2
3
My question is how to make a sql Query which first select the course by $row['id'] which indicates the id variable from the courses database, and after that based on the 3th table subscription to list all the users which are subscribed to this course number. ?
and second question is how to list number of the subscribed users for a course selected by
$row['id']
Here is some kind of the alghorytm logic that I have right now
SELECT * FROM users WHERE id=5.courses(select from the database 'courses') AND 5-> SELECT ALL FROM table subscriptions user_id equal to id from table users
Not sure if I understood what you try to achieve, but if you want a list that shows you every user in every course with the name of the course and ordered by course name, this should make the deal.
select t1.*, t2.*, t3.* from users as t1, courses as t2, subscriptions as t3 where t3.user_id = t1.userID and t3.curso_id = t2.id order by t2.id
Not the nicest way to do this and from a performance aspect I would recommend to put this in several statements as joins are usually slow.
okay I found the way and here is the mysql query:
FROM users
INNER JOIN subscriptions
ON users.userID = subscriptions.user_id
WHERE subscriptions.curso_id = $ids"