join two tables in mysql and get records - mysql

I have two tables "contacts" and "users". Users table storing data with "," separated. Need to distinct data in "Contacts" column from "Contacts" table. And need to join with "Users" table, and get the records.
Contacts Table
--------------------------
id | user_Id | contats
--------------------------
1 | 2147483647 | 90123456789,90123456789,90123456789,90123456789
2 | 2147483647 | 90123456789,90123456789,90123456789,90123456789
3 | 919444894154 | 90123456789,90123456789,90123456789,90123456789
Users Table
-----------------------------
id | username | email | phone
-----------------------------
1 | bhavan | bhavanram93#gmail.com | 90123456789
2 | bhavan | bhavanram93#gmail.com | 90123456789
3 | prince | prince#gmail.com | 1234567980
4 | bhavan | bhavanram93#gmail.com | 90123456789
5 | hello | hello#gmail.com | 1234567890
6 | bhavan | bhavanram93#gmail.com | 90123456789

Your table Contacts shouldn't be constructed this way.
Since you want 1 Users table containing all the data about a user, and 1 Contacts table containing links between different users, you'd rather do this kind of table structure :
Contacts table
id | user_id | contact_id
-------------------------
1 | 1 | 2
2 | 1 | 3
3 | 2 | 3
That'll allow you to do something like :
SELECT *
FROM Users
JOIN Contacts ON (Users.id = Contacts.contact_id)
WHERE Contacts.user_id = 1
Which will return all the data of the contacts of the user 1.
Your current structure is a huge ongoing mess, it's the opposite of being flexible.

You should restructure your db to a normalized format as Steve suggest.
But if you cant:
SELECT *
FROM Users
JOIN Contacts
ON CONCAT(',', Contacts.contacts, ',') like
CONCAT('%,', Users.phone, ',%')
WHERE Contacts.user_id = 1
the idea is you convert your contacts to
, <numbers> ,
,90123456789,90123456789,90123456789,90123456789,
and try to match with
%,90123456789,%
Note this approach cant use any index so will have bad performance with many
rows. if you are in the order of 1k-10k rows may be ok. More than that you need consider restructure your db.

Related

How to get all users which have more than 100 referrals?

I have a service which has a referrer system. There's table users in service's database which contains id and referrers columns. Column referrer contains a string of referrer ids that separated by ,. Here's an example data from this table:
+------+---------------+
| id | referrers |
+------+---------------+
| 1 | 1 |
| 7 | 1 |
| 8 | 1 |
| 9 | 1 |
| 10 | 7,1 |
| 11 | 1 |
| 12 | 7,1 |
| 13 | 1 |
| 14 | 9,1 |
| 20 | 7,1 |
I need smt like: SELECT id, login FROM users u WHERE id IN (SELECT id FROM users u1 WHERE *referrers count more than 1000*), but I don't understand what should I use in *..*. To see this situation more clearly, I need to get the current user id from the first query and add it to the subquery into the %LIKE% statement, but how? Like:
`SELECT
id, login
FROM users u
WHERE id IN
(SELECT id FROM users u1 WHERE count((SELECT * FROM users u2 WHERE refer LIKE %u1.id%) > 1000)`
But how to do it in right way?
You can use string functions for this:
select id, login
from users
where char_length(referrers) - char_length(replace(referrers, ',', '')) >= 99
This works by counting how many , can be found in the referrers column: 99 commas means that there are 100 values.
Bottom line, you should fix your data model: instead of using delimited lists, you should have a separate table to store the user/referrer tuples, with one tuple per row. Storing delimited lists in a table column is typical antipattern in relational databases that should generally be avoided: you can read more about this in this famous SO post.

Mysql - Compare int field with comma separated field from another table

I have two tables in a MySQL database like this:
User:
userid |userid | Username | Plan(VARCHAR) | Status |
-----------+------------+--------------+---------------+---------+
1 | 1 | John | 1,2,3 |1 |
2 | 2 | Cynthia | 1,2 |1 |
3 | 3 | Charles | 2,3,4 |1 |
Plan: (planid is primary key)
planid(INT) | Plan_Name | Cost | status |
-------------+----------------+----------+--------------+
1 | Tamil Pack | 100 | ACTIVE |
2 | English Pack | 100 | ACTIVE |
3 | SportsPack | 100 | ACTIVE |
4 | KidsPack | 100 | ACTIVE |
OUTPUT
id |userid | Username | Plan | Planname |
---+-------+----------+------------+-------------------------------------+
1 | 1 | John | 1,2,3 |Tamil Pack,English Pack,SportsPack |
2 | 2 | Cynthia | 1,2 |Tamil Pack,English Pack |
3 | 3 | Charles | 2,3,4 |English Pack,Sportspack, Kidspack |
Since plan id in Plan table is integer and the user can hold many plans, its stored as comma separated as varchar, so when i try with IN condition its not working.
SELECT * FROM plan WHERE find_in_set(plan_id,(select user.planid from user where user.userid=1))
This get me the 3 rows from plan table but i want the desired output as above.
How to do that.? any help Please
A rewrite off your query what should work is as follows..
Query
SELECT
all columns you need
, GROUP_CONCAT(Plan.Plan_Name ORDER BY Plan.planid) AS Planname
FROM
Plan
WHERE
FIND_IN_SET(Plan.plan_id,(
SELECT
User.Plan
FROM
user
WHERE User.userid = 1
)
)
GROUP BY
all columns what are in the select (NOT the GROUP_CONCAT function)
You also can use FIND_IN_SET on the ON clause off a INNER JOIN.
One problem is that the join won't ever use indexes.
Query
SELECT
all columns you need
, GROUP_CONCAT(Plan.Plan_Name ORDER BY Plan.planid) AS Planname
FROM
User
INNER JOIN
Plan
ON
FIND_IN_SET(Plan.id, User.Plan)
WHERE
User.id = 1
GROUP BY
all columns what are in the select (NOT the GROUP_CONCAT function)
Like i said in the comments you should normalize the table structures and add the table User_Plan whats holds the relations between the table User and Plan.

Split SQL field containing array into new table/rows

I need a list of user IDs (course_user_ids) that is currently stored in a single field of a larger table.
I have a table called courses that contains course information with course_id and course_students as such:
-----------------------------------------------------------
| course_id | course_students |
----------------------------------------------------------
| 1 | a:3:{i:0;i:12345;i:1;i:22345;i:2;i:323456;} |
-----------------------------------------------------------
| 2 | a:32:{ … } |
-----------------------------------------------------------
The course_students part contains 3 chunks of information:
the number of students (a:3:{…) -- not needed
the order/key for the array of each student ({i:0;… i:1;… i:2; …}) -- also not needed
the course_user_id (i:12345; … i:22345;… i:32345;)
I only need the course_user_id and the original course_id, resulting in a new table that i can use for joins/subqueries like this:
------------------------------
| course_id | course_user_id |
------------------------------
| 1 | 12345 |
------------------------------
| 1 | 22345 |
------------------------------
| 1 | 323456 |
------------------------------
(ideally able to continue to break out values for other course_ids and course_user_ids, but not a priority:)
| … | … |
------------------------------
| 2 | … |
------------------------------
| 2 | … |
------------------------------
| 97 | … |
------------------------------
| 97 | … |
------------------------------
| … | … |
------------------------------
Note: the course_user_id can vary in length (some are 5 digits, some are 6)
Any ideas would be much appreciated!
Update
My user table does have user_id which can be mapped to course_students or course_user_id, so that is a very helpful observation from below.
I also think I need to use a LEFT JOIN because some students are registered in multiple courses, and I'd like to see each instance/combo.
Let us assume that you have a table name users which contains all users data along with user_id.
Now you can join table courses and table users in following manner:
select c.course_id,u.user_id
from
courses c
join users u
on u.user_id=if(instr(c.course_students,concat(":",u.user_id,";"))>0,u.user_id,c.course_students)
You get the result as per your requirement.
Verify at http://sqlfiddle.com/#!9/3667d/2
Note: The above query works fine if no overlapping between user_id and array index. In case of overlapping, kindly filter data using where-clause
If I got your goal correctly you have users table. And {i:0;i:12345;i:1;i:22345;i:2;i:323456; equal users.id=12345,users.id=22345 etc.
If my guess is correct you can try this solution:
http://sqlfiddle.com/#!9/cfef27/5
SELECT * FROM courses
LEFT JOIN users u
ON courses.course_students LIKE CONCAT('%i:',u.id,';%')

how can we add two field in same column in sql table?

i want to create a database that consists all products rating and notes purchase by user
suppose that i create a table name "Users_rating_product" that consists some column
user_id ->INT
company->Varchar
product1 -> 3 (rating of product out of 5)|(review of product)
product2-> 4(rating)|(some review)
i want to know how can i do it in mysql . i'm using phpmyadmin for database creation
table looks like
user_id | company |Ac | TV | fridge
1 | goderaj |3 ,take more power |4,less power |5,efficient
i want to know how can i do this so that both rating and notes for product display in same column
For this you'll need a separate table. Call it ProductRating. Put a unique key (ID) to the table and reference that key to your Users_rating_product table.
For example:
Users_rating_product:
user_id | company |Ac | TV | fridge
1 | goderaj |1 | 2 | 3
2 | somecomp |4 | 5 | 6
ProductRating
ID | Rating | Review
1 | 3 | Take more power
2 | 4 | less power
3 | 5 | efficient
4 | 5 | excellent
5 | 1 | awful
6 | 3 | average
There are many ways that you can achieve your functionality.
but this is not standard format to write queries.
you can have comma seperated column in your database like this
user_id | company |Ac_mapping_id
1 | goderaj |1,REview for Ac
for Seperate two values you can do like this
PARSENAME(REPLACE(String,',','.'),2) 'Name'
for Detail Reference for splitting two values you can refer :
click To refer
Better Way is to store Product description in different table.
You can easily write queries to retrieve your data
user_id | company |Ac_mapping_id | TV_mapping_id | fridge_mapping_id
1 | goderaj |1 | 2 | 3
& store all the ratings & reviews in mapping table like this
Ac_mapping_id | Rating |Review
1 | 1 |abcd
So on for the other table.
For Retrieving all the data just Use Left outer join
Select
*
from
Users_rating_product mm
Left outer join Ac_mapping_table ac on ac.ac_mapping_id = mm.ac_mapping_id
.....so on

Application specific MySQL table Structure

I have a question about my DB table structure. I want to know if i'm on the right track or if I have missed a good alternative. Here is the case:
To make it easy to read, I haven't pasted the full contents as my question is only about the structure.
2 tables:
1: id (AI), task
2: id, name, task
Table 1 presents dynamic check-boxes which can be altered by an admin panel so the contents would be like this
1 task1
2 task2
5 task5
(3 & 4 are missing cause the administrator deleted those records).
In table number two are the people who should do the tasks from table 1. And the goal is that the tasks wich are not checked will be displayed.
So the contents of table 2 would be:
1 Name1 1,5
2 Name2 1,2
3 Name3 1,2,5
The numbers in table 2 represent the checked boxes from table 1. So with a query i can compare the numbers from table 2 with the id's from table 1 and display the missing ids as "todo".
In my opinion this looks very overdone, and there must be an easier way to create dynamic options which can be compared and stored as a todo.
Suggestions are welcome!
I suggest you to use basic structure for many-to-many relationship:
tasks users user_tasks
+----+-----------+ +----+-------+ +---------+---------+
| id | name | | id | name | | user_id | task_id |
+----+-----------+ +----+-------+ +---------+---------+
| 1 | Buy milk | | 1 | John | | 1 | 2 |
| 2 | Get drunk | | 2 | Tim | | 3 | 2 |
| 3 | Have fun | | 3 | Steve | | 2 | 4 |
| 4 | Go home | +----+-------+ | 3 | 4 |
+----+-----------+ +---------+---------+
And you can fetch unassigned tasks using following query:
SELECT
tasks.*
FROM
tasks
LEFT JOIN
user_tasks
ON (tasks.id = user_tasks.task_id)
WHERE
user_tasks.user_id IS NULL
You also can fetch users who have no assigned tasks:
SELECT
users.*
FROM
users
LEFT JOIN
user_tasks
ON (users.id = user_tasks.user_id)
WHERE
user_tasks.user_id IS NULL
Hope this will help you.