What is the best way to reduce MXN table search in MySQL - mysql

I have two MySQL tables called tasks and users. All I want to do is I don't want to display the tasks that is already done by a user in his panel. Suppose the task table has about 1000 entries and there are about 50000 users. Also the users and the tasks keep increasing.
One solution I can think of, 1st is creating a separate table of task x user size.
For example:
user table
+---------+--------+-------+
| user_id | fname | lname |
+---------+--------+-------+
| 1 | John | Smith |
| 2 | Steve | Mark |
+---------+--------+-------+
task table
+---------+-------------+---------------+
| task_id | task | task_duration |
+---------+-------------+---------------+
| 1 | Do task 1 | 1 hour |
| 2 | Do task 2 | 1 hour |
+---------+-------------+---------------+
Creating a separate table called display
+------------+---------+---------+
| display_id | task_id | user_id |
+------------+---------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
+------------+---------+---------+
So only listed tasks will be shown to the particular user.
The problem is that This does not look like an efficient solution. How can I design table in this scenario in an efficient way. If not what are the other ways?

Related

MySQL : Get critical path time

I have to manage a gantt like interface where we can have multiple project (project_id). And need to get the minimum time to accomplish a project
My tables are the following :
Task
+---------+-------+----------------+
| id_task | name | days_allocated |
+---------+-------+----------------+
| 1 | task1 | 2 |
| 2 | task2 | 3 |
| 3 | task3 | 0.5 |
| 4 | task4 | 4 |
+---------+-------+----------------+
Task_predecessor (both field are linked to Task.id_task)
+------+-------------+
| task | predecessor |
+------+-------------+
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 4 | 3 |
+------+-------------+
Progress
+-------------+---------+------------+---------+
| id_progress | task_id | project_id | current |
+-------------+---------+------------+---------+
| 1 | 1 | 1 | 0 |
| 2 | 2 | 1 | 1 |
| 3 | 3 | 1 | 1 |
| 4 | 4 | 1 | 1 |
| 5 | 1 | 2 | 0 |
| 6 | 2 | 2 | 0 |
+-------------+---------+------------+---------+
So the Task table is our "template" and we track the advancment in the Progress table.
In this case, for project_id = 1, the id_task 1 is already done (progress.current is 0 where project_id = 1 AND task_id = 1)
So it's either tasks id_task 2 + id_task 4 or id_task 3 + id_task 4.
id_task 2 take more time than id_task 3 so the critical path is id_task 2 --> id_task 4 , 7 days
I have 2 options :
Option n°1
I can add a minimal_days column in my Task table because I know the predecessors. So the table will be
+---------+-------+----------------+--------------+
| id_task | name | days_allocated | minimal_days |
+---------+-------+----------------+--------------+
| 1 | task1 | 2 | 9 |
| 2 | task2 | 3 | 7 |
| 3 | task3 | 0.5 | 4.5 |
| 4 | task4 | 4 | 4 |
+---------+-------+----------------+--------------+
And I can retrieve the minimal days with this kind of query :
SELECT MAX(minimal_days) FROM progress
LEFT JOIN task ON task.id_task = progress.task_id
WHERE project_id = 1 AND current = 1
Option n°2
I rewrite the logic in a MySQL query ? But honestly, I dont know how ...
Option n°1 can be easily implemented, the result will be nearly instantaneous but the system is pretty limited, if a task is added or removed, all days_allocated must be recalculed and updated.
Option n°2 is in my opinion most difficult to write in MySQL. The request may be slower. Especially if we have to retrieve it for several projects at once. Once agin is a suposition... But the system will be more modular.
I prefear the option n°2, what about you ? Should I prefear another option ? Is there any other way to proceed ? Can you help me to write this logic in MySQL ?
PS : We can work with a total of 50 - 100 project at a time. A project can have 30 tasks max and the task_predecessor thing is pretty linear. We don't have very complex schema. So I think the result can be displayed in "real-time"

MySQL: Hundreds of tables or one big table?

I want to create a webpage where user can organize things they collect. As everyone collects something else I want to have the users create their own datamodell (with strict limitations). If two people are collection the same "things" they can share a datastructure.
My idea was to give every collection an ID and all the tables belonging to that collection will have the ID as a prefix.
Table: Collections
ID | Collection
1 | Poststamps
2 | Barbie Dolls
Table: 1_Base
ID | StampValue | StampPic
....
Table: 2_Base
ID | EAN | Pic
....
Thus I would create many tables as each user could in theory create their own collection. I could also use only one very big table and a mapping table. Example:
Table: Colleactions
ID | Collection
1 | Poststamps
2 | Barbie Dolls
Table: Mapping
fkCollection | FieldName | Mapping
1 | DoubleField1 | StampValue
1 | BlobField1 | StampPic
2 | StringField1 | EAN
2 | BlobField1 | StampPic
Table: CollectionData
fkCollection | DoubleField1 | ... | DoubleField10 | StringField1 | ... | Stringfield10 | BlobField1 | ...
1 | 30 | | | | | | ... |
2 | | | | 21312412414 | | | ... |
Any other ideas?
Thanks for your help!
From what I can see, your second way of attempting this is going to be the easiest way... your queries will be ten fold simpler to handle, and you wouldn't need to programmably create tables on the fly... so my suggestion would be to modify your second idea slightly... Just to clarify something also, A blob will slow down the query speed so I am changing the block to hold the source link to the image instead.
TABLE: Collections
ID| Collection
1 | Poststamps
2 | Barbie Dolls
Table: CollectionData
fkCollection | DataType | VALUE | FieldName |
1 | Double | 30 | StampID |
1 | String | London | StampName |
1 | ImgSrc | ../loc | StampPic |
2 | String | Ken | BarbieName |
2 | ImgSrc | ../loc | BarbiePic |

sql query to find users with at least 2 types of accounts

I'm new to relational sql. I'm trying to figure out a query to return the names of customers who have more than one type of account.
customers:
+------------+--------------+
| cid | Name |
+------------+--------------+
| 1 | Bob |
| 2 | John |
| 3 | Jane |
+------------+--------------+
accounts:
+------------+--------------+
| aid | type |
+------------+--------------+
| 1 | Checking |
| 2 | Saving |
| 3 | CD |
+------------+--------------+
transactions:
+------------+--------------+--------------+
| tid | cid | aid |
+------------+--------------+--------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 3 |
| 5 | 3 | 1 |
+------------+--------------+--------------+
With these tables, the query should return Bob and John. I'm having some trouble with how to write such a query. More specifically, how do I keep count of how many accounts a customer has and how do I compare if the accounts are different without adding a new column to the table?
Okay, this seems to work in SQL Fiddle with my test data structure. Try it out with your real data structure and see if it gives you what you're looking for.
SELECT name FROM customers c WHERE EXISTS(
SELECT DISTINCT aid FROM transactions
WHERE cid = c.cid
HAVING COUNT(DISTINCT aid)>1
)

Assistance with database design

I've got a excel sheet that contains all the employees that have worked for my company and is still working for us. It's a sheet of around 200 rows. Each row has basic info, like surname, name, position, qualification etc etc. 16 columns of basic info. Now, the tricky part is this. After the 16 columns, there are months (May-05 up to the present (Apr-12)). Under every month column, an employee either get's a 0 (contract), 1 (permanent), 2 (contract-terminated) or 3 (student).
What would be the best way to do this? I was thinking of 4 tables (listed below), where the one table determines permanently terminated people (for the sake of knowing who was on what type of employment).
MySQL Table: hr_employees
|-----------------|-------|----|----|----|
| employee_number | name | sur| etc| etc|
|-----------------|-------|----|----|----|
| 1 | Dave | F | xx | xx |
|-----------------|-------|----|----|----|
MySQL Table: hr_month
|----|--------|
| id | month |
|----|--------|
| 1 | May-05 |
| 2 | Jun-05 |
|----|--------|
MySQL Table: hr_status
|----|------|------|--------|
| id | e_no | date | status |
|----|------|------|--------|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 |
|----|------|------|--------|
MySQL Table: hr_terminated
|----|------|
| id | e_no |
|----|------|
| 1 | 1 |
| 2 | 1 |
|----|------|
I hope you guys understand what I want to achieve, otherwise, ask a question, and I'll answer as best I can! :)
Thanks.
Here is a design that simplifies your data entry and is more relational database like and less Excel like, insofar as it's normalized.
MySQL Table: hr_employee
|-----------------|-------|----|----|----|
| employee_number | name | sur| etc| etc|
|-----------------|-------|----|----|----|
| 1 | Dave | F | xx | xx |
|-----------------|-------|----|----|----|
| 2 | Bob | M | xx | xx |
|-----------------|-------|----|----|----|
MySQL Table: hr_employee_status
|-----------------|------------|------------|--------|
| employee_number | from_date | to_date | status |
|-----------------|------------|------------|--------|
| 1 | 2005-05-01 | 2005-08-31 | 3 |
|-----------------|------------|------------|--------|
| 1 | 2006-05-01 | 2010-02-28 | 0 |
|-----------------|------------|------------|--------|
| 2 | 2010-03-01 | 9999-12-31 | 1 |
|-----------------|------------|------------|--------|
Here you can see that Dave was hired on as a student from May '05 to August '05, then he came back in May '06 as a contract employee which he worked as until the end of February '10. Then on March 1, 2010 Bob was hired as permanent employee and he is still working (max collating date means "until further notice").
The great advantage of this design is that you only have to enter/edit data when something changes, not once a month for every employee that you have or have ever had. You can also see what your workforce looked like at any given date (not just by months!) with a very simple SQL query.

Copying Relational Table Data

I hope I'm not being too long winded in this question, I just want to make sure that what I'm asking is completely clear (I think it's rather confusing :).
I've got a database with a bunch of tables with all my foreign key constraints set up. Relations are sometimes several tables deep, and there are also cases where a child is related to more than one parent table. I want to insert a copy of one of my "top level" table rows, and all of child table data that relates to it (keeping the relational integrity). That is to say my new top level row gets its own new primary key (via auto_increment), and all the new child rows get their own primary keys (again through auto_increment), and all the foreign key information of the tables relates analogously to the data I copied (only now with the newly created primary keys). So now I would have a copy of the relational data that was independently mutable from the original.
To make my example more concrete, I have painstakingly set up an analogous, but simpler example. Lets define the following tables:
alt text http://www.freeimagehosting.net/uploads/ef22070a89.png
All the green id fields are auto_update primary keys, and the yellowish ones are indexed columns with foreign key constraints. Lets say the database has the following data in it initially:
job_types
+----+----------+
| id | jobcode |
+----+----------+
| 1 | DEADBEEF |
| 3 | FEEDFACE |
+----+----------+
managers
+----+---------------+-------------+
| id | name | job_type_id |
+----+---------------+-------------+
| 1 | John | 1 |
| 3 | Michael Scott | 3 |
+----+---------------+-------------+
departments
+----+------+------------+
| id | name | manager_id |
+----+------+------------+
| 1 | H32 | 1 |
| 2 | X11 | 3 |
+----+------+------------+
employees
+----+-------------+---------------+------------+-------------+
| id | name | department_id | manager_id | job_type_id |
+----+-------------+---------------+------------+-------------+
| 1 | Billy Bob | 1 | 1 | 1 |
| 2 | Sandra Lee | 1 | 1 | 3 |
| 3 | Buddy Holly | 2 | 3 | 1 |
+----+-------------+---------------+------------+-------------+
Now say what I want to do is make a relational copy of department H32 (id=1).
What I should end up with is something like the following (obviously actual values of primary keys is not important, referential integrity is).
job_types
+----+----------+
| id | jobcode |
+----+----------+
| 1 | DEADBEEF |
| 3 | FEEDFACE |
| 4 | DEADBEEF |
| 5 | FEEDFACE |
+----+----------+
managers
+----+---------------+-------------+
| id | name | job_type_id |
+----+---------------+-------------+
| 1 | John | 1 |
| 3 | Michael Scott | 3 |
| 4 | John | 4 |
+----+---------------+-------------+
departments
+----+------+------------+
| id | name | manager_id |
+----+------+------------+
| 1 | H32 | 1 |
| 2 | X11 | 3 |
| 3 | H32 | 4 |
+----+------+------------+
employees
+----+-------------+---------------+------------+-------------+
| id | name | department_id | manager_id | job_type_id |
+----+-------------+---------------+------------+-------------+
| 1 | Billy Bob | 1 | 1 | 1 |
| 2 | Sandra Lee | 1 | 1 | 3 |
| 3 | Buddy Holly | 2 | 3 | 1 |
| 4 | Billy Bob | 3 | 4 | 4 |
| 5 | Sandra Lee | 3 | 4 | 5 |
+----+-------------+---------------+------------+-------------+
What's the most efficiently performing way to implement this type of copy operation? For what it's worth I'm working with MySQL, using the InnoDB table engine, in the context of Grails. I'm looking forward to hearing some good ideas on how you do something like this "the right way."
-- Regards, Vic
I've posted a MySQLDump of the example initialization on PasteBin.
EDIT
For what it's worth, I posted a much simpler / broader question here and I got generally positive responses, suggesting that I'm not "just doing it wrong"...
I have done a similar thing using INSERT INTO ... SELECT syntax. (The C api also has a MYSQL_OPTION_MULTI_STATEMENTS_ON which you can use to run multiple statements with. or you could use a procedure).
This is the most effective, since you do not have to move data between the client and the server. The value copied was a template to create a new entity. I don't understand why you are doing this with this particiluar data model.