MySQL split into two tables or keep everything in one - mysql

I've currently got a generic Users table with the following columns
user_id
first_name
last_name
join_date
last_active
email
password
rank
status
Some users (the ones with rank = 3) will provide some extra information like telephone number, secondary email, birthday, etc (total 15 fields). I was wondering if I should add these columns on this table or if I should create another table and connect with the Users one with user_id. Something like this:
user_id
all new columns
Which one would be the best option?

The two table approach is viable.
To get all columns from both tables:
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2 USING(user_id);
I as assuming that the row in t2 will be sometimes missing, yet you want to get the row, with NULLs for the missing data -- hence LEFT JOIN.
Of course, if you know that you won't need t2, don't do the JOIN. But there is no harm, other than a little performance, in always doing the JOIN.
Is it the "best option"? That is hard to say without knowing more about your system. But, based on what information you mention, it seems like a 'good' option.

Related

Mysql query for select data from multiple table with comparision

I have a three tables namely profile, academic,payment and these tables having two same columns that are username and status.
my problem is how to select username from the tables where status=1 in all the tables
Typically it works like this:
SELECT * FROM profile
LEFT JOIN academic ON profile.username=academic.username
LEFT JOIN payment ON profile.username=payment.username
WHERE profile.status=1 AND academic.status=1 AND payment.status=1
As a note having username as a key is usually a bad thing, often super bad since if someone's able to change their name you need to update N other tables. You may have a circumstance where you forget to update one or more tables, then subsequently someone registers with the former name and "inherits" this data.
It's also typically very inefficient to use a string INDEX key when a user_id integer value would suffice.

SQL Query to populate table based on PK of Main Table being joined

Here is my Database structure (basic relations):
I'm attempting to formulate a one-line query that will populate the clients_ID, Job_id, tech_id, & Part_id and return back all the work orders present. Nothing more nothing less.
Thus far I've struggled to generate this Query:
SELECT cli.client_name, tech.tech_name, job.Job_Name, w.wo_id, w.time_started, w.part_id, w.job_id, w.tech_id, w.clients_id, part.Part_name
FROM work_orders as w, technicians as tech, clients as cli, job_types as job, parts_list as part
LEFT JOIN technicians as techy ON tech_id = techy.tech_name
LEFT JOIN parts_list party ON part.part_id = party.Part_Name
LEFT JOIN job_types joby ON job_id = joby.Job_Name
LEFT JOIN clients cliy ON clients_id = cliy.client_name
Apparently, once all the joining happens it does not even populate the correct foreign key values according to their reference.
[some values came out as the actual foreign key id, not even
corresponding value.]
It just goes on about 20-30 times depending on largest row of a table that I have (one of the above).
I only have two work orders created, So ideally it should return just TWO Records, and columns, and fields with correct information. What could I be doing wrong? Haven't been with MySQL too long but am learning as much as I can.
Your join conditions are wrong. Join on tech_id = tech_id, not tech_id = tech_name. Looks like you do this for all your joins, so they all need to be fixed.
I really don't follow the text of your question, so I am basing my answer solely on your query.
Edit
Replying to your comment here. You said you want to "load up" the tech name column. I assume you mean you want tech name to be part of your result set.
The SELECT part of the query is what determines the columns that are in the result set. As long as the table where the column lives is referenced in the FROM/JOIN clauses, you can SELECT any column from that table.
Think of a JOIN statement as a way to "look up" a value in one table based on a value in another table. This is a very simplified definition, but it's a good way to start thinking about it. You want tech name in your result set, so you look it up in the Technicians table, which is where it lives. However, you want to look it up by a value that you have in the Work Orders table. The key (which is actually called a foreign key) that you have in the Work Orders table that relates it to the Technicians table is the tech_id. You use the tech_id to look up the related row in the Technicians table, and by doing so can include any column in that table in your result set.

How to store customer data in mysql (2 tables vs 1 table)

I was thinking that I would have two tables for mysql. One for storing login information and the other for shipping address. Is that the conventional way or is everything store in one table?
For two tables... is there a way where it automatically copies a column from table A to table B, so that I can reference the same id to grab their shipping address...
If its a single address and if it is going to be updated everytime , then you can have it in a single table something like
**Customer**
customer_id [pkey]
customer_name
login_id
password
shipping_address
whereas if you want to store all the shipping addresses for a single customer(across multiple visits) then it would be a good design to have another table customer_shipping_address
**Customer**
customer_id [pkey]
customer_name
login_id
password
**Customer_Shipping_Address**
customer_id [fkey to customer]
shipping_address
This is my answer to your question regarding using 1 table or 2 tables. This decision depends on may factors. But i would suggest that you should use 2 separate tables. Because the log-in information is something that you will be retrieving very often compare to shipping information. Now if you have all the info in one table then table size will be huge and you will have to query this huge table everytime you need login information of user.
I think using two tables is better way to go. then just join them when you want to do the shipping.
The SQL for that would be like this.
SELECT
table1.id, table2.id, table2.somethingelse, table1.somethingels
FROM
table1 INNER JOIN table2
ON table1.foreignkey = table2.primarykey
WHERE
(some conditions is true)
The code above would need to be run on the shiping page itself.

A MySQL query addressing three tables: How many from A are not in B or C?

I have a problem formulating a MySQL query to do the following task, although I have seen similar queries discussed here, they are sufficiently different from this one to snooker my attempts to transpose them. The problem is (fairly) simple to state. I have three tables, 'members', 'dog_shareoffered' and 'dog_sharewanted'. Members may have zero, one or more adverts for things they want to sell or want to buy, and the details are stored in the corresponding offered or wanted table, together with the id of the member who placed the ad. The column 'id' is unique to the member, and common to all three tables. The query I want is to ask how many members have NOT placed an ad in either table.
I have tried several ways of asking this. The closest I can get is a query that doesn't crash! (I am not a MySQL expert by any means). The following I have put together from what I gleaned from other examples, but it returns zero rows, where I know the result should be greater than zero.
SELECT id
FROM members
WHERE id IN (SELECT id
FROM dog_sharewanted
WHERE id IS NULL)
AND id IN (SELECT id
FROM dog_shareoffered
WHERE id IS NULL)
THis query looks pleasingly simple to understand, unlike the 'JOIN's' I've seen but I am guessing that maybe I need some sort of Join, but how would that look in this case?
If you want no ads in either table, then the sort of query you are after is:
SELECT id
FROM members
WHERE id NOT IN ( any id from any other table )
To select ids from other tables:
SELECT id
FROM <othertable>
Hence:
SELECT id
FROM members
WHERE id NOT IN (SELECT id FROM dog_shareoffered)
AND id NOT IN (SELECT id FROM dog_sharewanted)
I added the 'SELECT DISTINCT' because one member may put in many ads, but there's only one id. I used to have a SELECT DISTINCT in the subqueries above but as comments below mention, this is not necessary.
If you wanted to avoid a sub-query (a possible performance increase, depending..) you could use some LEFT JOINs:
SELECT members.id
FROM members
LEFT JOIN dog_shareoffered
ON dog_shareoffered.id = members.id
LEFT JOIN dog_sharewanted
ON dog_sharewanted.id = members.id
WHERE dog_shareoffered.id IS NULL
AND dog_sharewanted.id IS NULL
Why this works:
It takes the table members and joins it to the other two tables on the id column.
The LEFT JOIN means that if a member exists in the members table but not the table we're joining to (e.g. dog_shareoffered), then the corresponding dog_shareoffered columns will have NULL in them.
So, the WHERE condition picks out rows where there's a NULL id in both dog_shareoffered and dog_sharewanted, meaning we've found ids in members with no corresponding id in the other two tables.

How do I select a record from one table in a mySQL database, based on the existence of data in a second?

Please forgive my ignorance here. SQL is decidedly one of the biggest "gaps" in my education that I'm working on correcting, come October. Here's the scenario:
I have two tables in a DB that I need to access certain data from. One is users, and the other is conversation_log. The basic structure is outlined below:
users:
id (INT)
name (TXT)
conversation_log
userid (INT) // same value as id in users - actually the only field in this table I want to check
input (TXT)
response (TXT)
(note that I'm only listing the structure for the fields that are {or could be} relevant to the current challenge)
What I want to do is return a list of names from the users table that have at least one record in the conversation_log table. Currently, I'm doing this with two separate SQL statements, with the one that checks for records in conversation_log being called hundreds, if not thousands of times, once for each userid, just to see if records exist for that id.
Currently, the two SQL statements are as follows:
select id from users where 1; (gets the list of userid values for the next query)
select id from conversation_log where userid = $userId limit 1; (checks for existing records)
Right now I have 4,000+ users listed in the users table. I'm sure that you can imagine just how long this method takes. I know there's an easier, more efficient way to do this, but being self-taught, this is something that I have yet to learn. Any help would be greatly appreciated.
You have to do what is called a 'Join'. This, um, joins the rows of two tables together based on values they have in common.
See if this makes sense to you:
SELECT DISTINCT users.name
FROM users JOIN conversation_log ON users.id = converation_log.userid
Now JOIN by itself is an "inner join", which means that it will only return rows that both tables have in common. In other words, if a specific conversation_log.userid doesn't exist, it won't return any part of the row, user or conversation log, for that userid.
Also, +1 for having a clearly worded question : )
EDIT: I added a "DISTINCT", which means to filter out all of the duplicates. If a user appeared in more than one conversation_log row, and you didn't have DISTINCT, you would get the user's name more than once. This is because JOIN does a cartesian product, or does every possible combination of rows from each table that match your JOIN ON criteria.
Something like this:
SELECT *
FROM users
WHERE EXISTS (
SELECT *
FROM conversation_log
WHERE users.id = conversation_log.userid
)
In plain English: select every row from users, such that there is at least one row from conversation_log with the matching userid.
What you need to read is JOIN syntax.
SELECT count(*), users.name
FROM users left join conversion_log on users.id = conversation_log.userid
Group by users.name
You could add at the end if you wanted
HAVING count(*) > 0