how I can use array in cell related with another table in database like ?
Users table:
Name | languages_id
Anas | 1,2,3
Languages table:
id | language
1 | English
2 | Arabic
it’s work or not ?! and do you know what can I use in yii to do this ?
Don't do this.
Don't store mutiple items as comma separated column, it is really bad.
You should keep your tables normalized, by creating a new table UsersLanguages as a many to many table between the USERS and Languages table. Somrthing like this:
Users:
UserId,
UserName,
... other details.
Languages:
LanguageId,
LanguageName,
...
UserLanguages:
UserId foreign key references Users(UserId),
LanguageId foreign kery references Languages(LanguageId).
You can use FIND_IN_SET.
SELECT
name,
language
FROM
users
INNER JOIN
languages ON FIND_IN_SET(languages.id, languages_id) != 0
GROUP BY
name
Although Mahmoud Gamal's comment would perhaps be the better way to go about it.
Related
I have a weird problem.
I have a rather large database with two tables. I need to change a column's contents from a name to an ID that already exists in another table.
Example:
I have a table that contains a column "Name"
the name column has the persons "lastname, firstname" as shown
Name | othercolumn
Smith, John |
I would like to change the contents of the name column to the staffID associated with the persons name.
The staff table is
staffID | firstName | lastName
1 john smith
My end result should be
Name | othercolumn
1 |
I've tried all sorts of joins and concats, but can't seem to get it down with my limited mysql knowledge. Is there a way to do this without having to do it manually? The comma seems to give me alot of grief. Thanks!
You need to be very careful about this. First, I assume that StaffId is a number. So, add a column to the table:
alter table t add StaffId int;
Then, update this column:
update t join
staff s
on t.name = concat_ws(',', s.lastname, s.firstname)
set t.StaffId = s.StaffId;
Note that after you have done this, you may still have StaffId values that are NULL:
select t.*
from t
where t.StaffId is null;
These are the names that are not in the staff table. They require more work. When you are done, you can drop the name column.
I have a small problem with a php mysql query, I am looking for help.
I have a family tree table, where I am storing for each person his/her ancestors id separated by a comma. like so
id ancestors
10 1,3,4,5
So the person of id 10 is fathered by id 5 who is fathered by id 4 who is fathered by 3 etc...
Now I wish to select all the people who have id x in their ancestors, so the query will be something like:
select * from people where ancestors like '%x%'
Now this would work fine except, if id x is lets say 2, and a record has an ancestor id 32, this like query will retrieve 32 because 32 contains 2. And if I use '%,x,%' (include commas) the query will ignore the records whose ancestor x is on either edge(left or right) of the column. It will also ignore the records whose x is the only ancestor since no commas are present.
So in short, I need a like query that looks up an expression that either is surrounded by commas or not surrounded by anything. Or a query that gets the regular expression provided that no numbers are around. And I need it as efficient as possible (I suck at writing regular expressions)
Thank you.
Edit: Okay guys, help me come up with a better schema.
You are not storing your data in a proper way. Anyway, if you still want to use this schema you should use FIND_IN_SET instead of LIKE to avoid undesired results.
SELECT *
FROM mytable
WHERE FIND_IN_SET(2, ancestors) <> 0
You should consider redesigning your database structure. Add new table "ancestors" to database with columns:
id id_person ancestor
1 10 1
2 10 3
3 10 4
After -- use JOIN query with "WHERE IN" to choose right rows.
You're having this issue because of wrong design of database.First DBMS based db's aren't meant for this kind of data,graph based db's are more likely to fit for this kind of solution.
if it contain small amount of data you could use mysql but still the design is still wrong,if you only care about their 'father' then just add a column to person (or what ever you call it) table. if its null - has no father/unknown otherwise - contains (int) of his parent.
In case you need more then just 'father' relationship you could use a pivot table to contain two persons relationship but thats not a simple task to do.
There are a few established ways of storing hierarchical data in RDBMS. I've found this slideshow to be very helpful in the past:
Models for Hierarchical Design
Since the data deals with ancestry - and therefore you wouldn't expect it to change that often - a closure table could fit the bill.
Whatever model you choose, be sure to look around and see if someone else has already implemented it.
You could store your values as a JSON Array
id | ancestors
10 | {"1","3","4","5"}
and then query as follows:
$query = 'select * from people where ancestors like \'%"x"%\'';
Better is of course using a mapping table for your many-to-many relation
You can do this with regexp:
SELECT * FROM mytable WHERE name REGEXP ',?(x),?'
where x is your searched value
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,ancestors VARCHAR(250) NOT NULL
);
INSERT INTO my_table VALUES(10,',1,3,4,5');
SELECT *
FROM my_table
WHERE CONCAT(ancestors,',') LIKE '%,5,%';
+----+-----------+
| id | ancestors |
+----+-----------+
| 10 | ,1,3,4,5 |
+----+-----------+
SELECT *
FROM my_table
WHERE CONCAT(ancestors,',') LIKE '%,4,%';
+----+-----------+
| id | ancestors |
+----+-----------+
| 10 | ,1,3,4,5 |
+----+-----------+
table
ID|owner_id|work_id|lorem|etc|
1 |00123 | 00213 |XXXXX|XXX|
2 |00124 | 00213 |XXXXX|XXX|
owner_id (fk) owners.id (owners[id,name,etc])
work_id (fk) work.id (work[id,name,etc])
question is can I set codeigniter that when I
select(table.*,work.name as work,owners.name as owner) from table
it automatically handle joins since that table already contain the fk-ref ? or I must include join('owner','owner.id=table.owner_id) ?
actually all what I want is that when I select a table that contains a fk this fk column is replaced with one column from ref row by just passing the column name on ref table without having to worry about creating a specific function in my module for that each query.
My current solution:
was to create a view for each table that contain a relation and replace all fk columns with desired ref value, but since i have 6 tables 5 of them with fk,i now have 6 tables and 5 view (11 tables)in db which is really kind confusing for me, so any smarter way to do this ?
I think you are making some confusion on what FK is and what it does within a table.
FK constraint grants data integrity when it's present and relates data within tables. It doesn't join anything.
If you want to select records across related tables, you either use a
SELECT * FROM table1,table2 WHERE table1.K1 = table2.FK1
or
SELECT * FROM table1 JOIN table2 ON table1.K1 = table2.FK1
AND YES, you need to tell CodeIgniter to do those queries
The title pretty much says it all. I have users posting content, and I would like to attach the user ID that is in the users table to the posts. Should I add a userid column in the posts table, should I join via the DB language, or should I use the scripting language to poll each table? If I should join, what kind of join should I do?
Sample content would look like this: "The teddy bears at my store are softer than the teddy goats, but the teddy goats are more lovable." - Posted by James Teddyman at 3:36 PM.
A very often-used concept in situation like this is by having a users table and a post table, linking them together with a unique identifier. This identifier can be anything - a serialized id, a user name, mail address, etc - as long as it's unique. Linking is done using a foreign key constraint. Exactly how this is achieved in MySQL I do not know, but in Postgres it's done like this:
CREATE TABLE users (
id serial PRIMARY KEY,
name text
);
CREATE TABLE posts (
content text,
user_id integer REFERENCES users(id) NOT NULL
);
The tables are then merged using a join. This can be done in several ways, but here is a cross join after insertion of some values to play with:
#> INSERT INTO users (name) VALUES ('James');
#> INSERT INTO users (name) VALUES ('Jones');
#> INSERT INTO posts (content, user_id) VALUES ('Hello from James.', 1);
#> INSERT INTO posts (content, user_id) VALUES ('Greetings from Jones.', 2);
#> SELECT U.id AS user_id, U.name, P.content \
FROM users U, posts P \
WHERE U.id = P.user_id;
user_id | name | content
---------+-------+-----------------------
1 | James | Hello from James.
2 | Jones | Greetings from Jones.
YMMV in MySQL, but I think the constructions above will work straight off.
(edit: Added INSERTs for clarification)
The pretty much way is to add a user id in the post table. Insert user id which each post. Then by extracting the information use the simple join to get the complete information. You select query should looks like
select post.content,post.date,users.firstname,user.lastname from post,users where post.userid=users.id
Database Normalization would suggest that the best method is "two tables with columns", relating user content to user via user_id. This method is known to manage both bears and goats more efficiently in the long-run.
I have 3 employers IDs: 1, 2 and 3. I am generating tasks for each one by adding a line in database and in column "for_emp" I insert IDs I want to assign this task for and could be all 3 of them separated by comma. So let's say I got a task and "for_emp" is "1,2,3", the employers IDs. If I would like to select all tasks for the ID 2, will I be able to select from the row that has "1,2,3" as IDs and just match "2" there ? If not, how do you suggest I insert my emp IDs into one row in database ? The db is MySQL.
Any ideas ? Thanks.
Don't do it like that, you should normalize your database.
What you want to do is have a table such as task, and then task_assignee. task_assignee would have fields task_id and user_id. If a task has eg. three assignees (IDs 1, 2 and 3), then you'll create three rows in the task_assignee table for that one task, like this:
+--------+---------+
|task_id | user_id |
+--------+---------+
| 1 | 1 [
| 1 | 2 [
| 1 | 3 [
+--------+---------+
Then it's just a simple matter of querying the task_assignee table to find all tasks that are assigned to a given user.
Here's an example of how to get all the tasks for user_id 2:
SELECT t.* FROM task AS t INNER JOIN task_assignee AS ta WHERE ta.user_id = 2
EDIT.
Just as a related note, even if you didn't do it the right way (which I described in my answer previously), doing it with hacks such as LIKE would still be far from the optimal solution. If you did store a list of comma-separated values, and needed to check if eg. the value 2 is in the list, you could use the MySQL's FIND_IN_SET function:
SELECT * FROM task WHERE FIND_IN_SET(2, for_emp)
But you shouldn't do this unless you have no choice (eg. you're working with someone's shitty DB design), because it's way more inefficient and won't let you index the the employee ID.
The following query should do what you want:
SELECT * FROM tasks WHERE for_emp LIKE '%2%';
However, be aware that that would also match employers 12, 20, 21 etc; so take care if you expect you might end up in double-digits.
However, the other answers about renormalising your database are definitely preferable.
You're doing it wrong. Create a relation table with two fields: employee id and task id. If one task should be assigned to three employees, insert three rows in the relation table.
You then use JOIN to join the task, employee and relation tables.
then its no proper relation...
I would suggest a "mapping table" for the n:m relation
employee
id
task
id
employeetask
task_id
employee_id
Make a table for your employers. Insert your three rows in it.
Then make a table for mapping tasks to employers. If a task is assigned to three employers, insert three rows into this table. This is basic entity-relation work.
I would make 2 different tables.
1 with employees, and 1 with tasks.
then make another table which combines the two tables, I will call it Assigned Tasks.
Then in assigned tasks I make a assigned id, a employeenumber which is a FK to the employee table and a taskid which is a FK to the Tasks table.
If an employee has more than 1 task. Just insert another row in the assigned table. ;)
When its about Databases, try to think in solo entities! Combining those entities is able in antoher table.
sql example:
Select * from Assignedtasks where employeeID = 1 will give you all his/her tasks. :)
You could use a LIKE '%,2,%' clause in your SELECT statement.
eg:
SELECT * FROM table where for_emp LIKE '%,2,%'
However performance of such non-sargable queries is usually quite bad.
I would suggest that you insert a row each for each employee who is assigned to the task using a separate TASK_EMPLOYEE_MAPPING table with taskId, employeeId as a composite primary key.
With such a design, your query will be
SELECT * FROM TASK_EMPLOYEE_MAPPING WHERE employeeId = '2'