my website includes a mysql db with two tables.
one table has a field called 'id_array', and it contains a string look like this:
'1,3,7,78,89,102'. it represents an array of id's in the second table.
what is the best strategy for retrieving the id's in the second table?
i want the fastest way.
currently i am using 'SELECT * FROM first_table WHERE id IN (id_array)'.
i used to query one by one, but i assume it is a lot slower.
if someone has a better structure to offer me for the db, that would be great.
this structure is the best i came up with, but i'm pretty sure it is not so efficiant.
i need a fast and convenient way to find all the id's that belong to the id from the first table.
help would be appreciated.
A comma separated value means the data is denormalized -- the IN clause won't work for you, because it works on distinct values.
Short Term Solution
Use MySQL's FIND_IN_SET function, like this:
SELECT *
FROM first_table
WHERE FIND_IN_SET(id, id_array)
Long Term Solution
...is not to store values in this manner, which means having a table to store the distinct values and a table to join that table of distinct values to the original table. IE:
FIRST_TABLE
first_table_id (primary key)
FIRST_TABLE_TYPE_CODES
type_code_id (primary key)
FIRST_TABLE_TYPE_MAP
first_table_id (primary key)
type_code_id (primary key)
You have a field that holds the ids that the record is related to in another table? You might want to create a lookup table that links the two tables together to help you with a many to many relationship. Post a little bit more or your db setup
Related
Let's say there is a database with two tables: one customer table and one country table. Each customer row contains (among other things) a countryId foreign key. Let's also assume that we are populating the database from a data file (i.e., it is not an operator that is selecting a country from a UI).
What is the best practice for this?
Should one query the database first and get all ID's for all countries, and then just supply the (now known) country id's in the insert query? This is not a problem for my 'country' example, but what if there is a large number of records in the table that is being referred?
Or should the insert query use a sub query to get the country id based on the country name? If so, what if the record for the country does not exist yet and has to be added?
Or another approach? Or does it depend? :)
I would suggest using a join in your insert query to get the country id based on the country name. However, I don't know if that's something possible with every SGBD and you don't give more precision on the one you're using.
I have 2 tables.
First table is called professions, and those are indexed by ID. So each profession now has a unique ID associated with it.
My second table is called contacts, and in there I have a profession field that right now only hold the ID that a certain profession is associated with.
My problem is that what if I have a contact that has more than one profession associated with it.
What would be the best way to query the table and ways to store the professions of a contact. I didn't want to do is create a field to just store a 0 or 1 int for each profession I have. The reason is because I want to dynamically grow the professions table and have the numbers reflect any dynamic changes on my site when I query.
You have a many-to-many relationship. To implement that in MySQL you should use a linking table. So professions and contacts should have an id in each table, but no foreign keys, and you create a new table called profession_contact_links or something, containing its own id, and profession_id and contact_id, which are both foreign keys to the respective tables. Then you can have many contacts linked with each profession, and many professions linked with each contact. To connect the two main tables together in a select you will need two joins, and what they are will depend on what exactly you want to select.
The standard solution to this modelling issue is called a link table.
Basically it is a table that contains the ids of the two tables that are linked, so you would have a link table with to columns and a primary key that is both of those columns:
(profession_id, contact_id)
or the other order... doesn't matter that much, but the order can affect performance, the key you will be searching on most often is the one you want first.
You then use either SELECT ... IN (...) or SELECT ... JOIN ... to query the data that you are after.
Depending on what you want and how you want to find it, i'd suggest rlike or in
SELECT ... FROM <table> WHERE <column name> RLIKE "^id1|id2|id3$"
This will find any cell that contains any of those three terms
or use
SELECT ... FROM <table> Where <column name> IN ('id1','id2','id3')
this will find any cell that is equals to one of those three.
Disclaimer: I didn't design these tables, and am aware they're not the best way to store this data. I need advice on the best way to handle the situation.
I have two MySQL tables:
`students`
id int; primary, unique
prof1_id varchar
prof2_id varchar
prof3_id varchar
`professors`
id int; primary, unique, auto-increment
username varchar
fname varchar
fname varchar
students_id int
comment text
A professor's username may be in any of the last three columns in the students table. Professors will need to provide one comment for each student who has them in their row in the students table.
The application that is the front end to this database expects two more columns in the professors table: student_id and comment. Since each student may have any 3 professors in their row, new rows will need to be added to professors whenever they are listed for multiple students. This means that the professors id field will need to auto increment for each new student comment.
What is the best way to accomplish this data transfer with a MySQL query? I've tried looking at UPDATE in combination with JOIN, but I'm not sure there is even a valid way to do this. Also, do I need to create another primary key for professors since the multiple rows will have the same id?
I suspect that a VIEW might be the best way to accomplish this, but the application on the front end expects the information to be stored in the professors table.
One other thing I was considering was that I could create a new table by joining the two tables and have a two-column primary key, students.id, professor.id.
Thanks!
Also, do I need to create another primary key for professors since the
multiple rows will have the same id?
Yes. This is good idea.
I wrote simple query that merges data from first table into 2 columns. This is not complete answer, but it can help you a lot:
SELECT id, prof1id as profid
UNION
SELECT id, prof2id
UNION
SELECT id, prof3id
UNION;
You may use this for view, inserts, but im not familiar with specyfic MySQL syntax and i dont want to misslead you. Please give feedback if it work.
"UNION" removes duplicate rows, you may need to use "UNION ALL" to keep duplicates (like duplicated values in 2 or 3 professors columns).
I'm wondering how to store a list of ID indexes for each id in a table. These will effectively form "relations" between the IDs. Here's the main table so far:
table main:
id, integer, primary key
name, varchar
text_info_1, varchar
text_info_2, varchar
And now for each row, there will be some list of other rows' IDs which will show me how one row relates to the next. For example, the row with id #5 might be related to IDs 6,7,9,25,...etc.
Here are the options I've considered:
Create a new column as a text field and store a serialized list of these integer values. Then just unserialize when I want them.
Create a new table called "relations" with columns relation_id (int auto increment primary key), name1, name2, [and optional other fields specifying the relation type, which would be nice].
I feel like option 1 is a bit of a hack. I've done it before and it works, but perhaps option 2 is better design?
I'm worried about speed though. With option 1 I can just do SELECT relations FROM main WHERE id = $id, and then unserialize the result and have my array with integer indices. But with option 2 I'll have to browse through a table that will be many times (10x or more) larger, and do "SELECT name1, name2 FROM relations".
Speed is my main priority here. I'm not sure which one is better for space, though I would be curious to find out.
So which option should I go with? Are there other good options I haven't considered? I'd also appreciate some good general pointers on database design!
Thanks a bunch.
Second option is better. If you want to get better in database design, you should read about database normalization. Sadly, all the materials I've used were not in English. This wikipedia link
could be a start.
Table relations:
relation_id (int auto increment primary key)
id_one (int)
id_two (int)
...
Instead of storing names in the relations table, you store ids.
I have a column in my table called student_id, and I am storing the student IDs associated with a particular record in that column, delimited with a | character. Here are a couple sample entries of the data in that column:
243|244|245
245|1013|289|1012
549|1097|1098|245|1099
I need to write a SQL query that will return records that have a student_id of `245. Any help will be greatly appreciated.
Don't store multiple values in the student_id field, as having exactly one value for each row and column intersection is a requirement of First Normal Form. This is a Good Thing for many reasons, but an obvious one is that it resolves having to deal with cases like having a student_id of "1245".
Instead, it would be much better to have a separate table for storing the student IDs associated with the records in this table. For example (you'd want to add proper constraints to this table definition as well),
CREATE TABLE mytable_student_id (
mytable_id INTEGER,
student_id INTEGER
);
And then you could query using a join:
SELECT * FROM mytable JOIN mytable_student_id
ON (mytable.id=mytable_student_id.mytable_id) WHERE mytable_student_id.student_id = 245
Note that since you didn't post any schema details regarding your original table other than that it contains a student_id field, I'm calling it mytable for the purpose of this example (and assuming it has a primary key field called id -- having a primary key is another requirement of 1NF).
#Donut is totally right about First Normal Form: if you have a one-to-many relation you should use a separate table, other solutions lead to ad-hoccery and unmaintainable code.
But if you're faced with data that are in fact stored like that, one common way of doing it is this:
WHERE CONCAT('|',student_id,'|') LIKE '%|245|%'
Again, I agree with Donut, but this is the proper query to use if you can't do anything about the data for now.
WHERE student_id like '%|245|%' or student_id like '%|245' or student_id like '245|%'
This takes care of 245 being at the start, middle or end of the string. But if you aren't stuck with this design, please, please do what Donut recommends.