I just realized that I'm going to have to start aliasing my database calls due to repeating column names in my join tables. Is there a way to automatically tell SQL to alias all my column names so that they are returned with a prefix of the table name? Otherwise it appears to be quite confusing when only some of them are aliased. Just trying to be consistent without writing tons of extra code.
$sql = "SELECT contracts.po_number, contracts.start_date, contracts.end_date, contracts.description, contracts.taa_required, contracts.account_overdue, jobs.id AS jobs_id, jobs.job_number, companies.id AS companies_id, companies.name AS companies_name
FROM contracts
LEFT JOIN jobs ON contracts.job_id = jobs.id
LEFT JOIN companies ON contracts.company_id = companies.id
WHERE contracts.id = '$id'
ORDER BY contracts.end_date";
No, but you can make life a little easier by using table aliases:
SELECT c.po_number, c.start_date, c.end_date, c.description,
c.taa_required, c.account_overdue, j.id AS jobs_id, j.job_number,
cm.id AS companies_id, cm.name AS companies_name
FROM contracts c
LEFT JOIN jobs j ON c.job_id = j.id
LEFT JOIN companies cm ON c.company_id = cm.id
WHERE c.id = '$id'
ORDER BY c.end_date
you can use alias tables in your sql statements so you have to write less, but to actually access the columns from php there's no way around aliasing all of them, if you want to access them by name.
you can also access columns with indexes from php, but that's a maintenance nightmare
I would recommend to always alias table names. It makes it very hard to read later, if you skip alias.
For info, theres a gotcha in MySQL 5.6 (possibly others!)
SELECT *
FROM table1
LEFT JOIN table2 ON PKI = FKI
works as expected.. but recently I mispelt 'LEFT' as 'LEFY' in a query and it also worked but with a standard join! so therefore
SELECT *
FROM table1
LEFY JOIN table2 ON PKI = FKI
also works just fine as does any substitute for the word LEFY, so beware a typo changing your query !!
Related
I have a MySQL database that has three tables holding information about uploaded photos by users. I have a PHP page that displays all the photos in the database (tbl_uploads) and who uploaded them (tbl_users). To display the photos and who uploaded them I have a join in the MySQL query.
SELECT *
FROM tbl_uploads, tbl_users
WHERE tbl_uploads.user_id = tbl_users.user_id
ORDER BY date DESC
I now want to join a third table tbl_collab to the MySQL query that allows me to display all the users that collaborated with the photo (a form allows them to post the $file and their $user_id to tbl_collab). I guess I need to add a join from tbl_uploads.file with tbl_collab.user_id but I'm not sure how.
tbl_users
|//**user_id**//|int(11)|No|
|user_name|varchar(25)|No|
|user_email|varchar(60)|No|
|user_password|varchar(255)|No|
|joining_date|datetime|No|
tbl_uploads
|//**id**//|int(10)|No|
|file|varchar(100)|No|
|type|varchar(30)|No|
|size|int(11)|No|
|user_id|int(11)|No|
|user_name|varchar(25)|No|
tbl_collab
|//**id**//|int(11)|No|
|user_name|varchar(100)|No|
|user_id|int(11)|No|
|file|varchar(255)|No|
I have been trying your various suggestions and I can't really get them to work as I would hope so I have made a mysql fiddle that might be help me.
The problem is that when I loop through the rows that the query throws up in PHP I ether get just the rows where there is join with tbl_uploads.file and tbl.collab.file or I get the multiple rows duplicating themselves.
I'd suggest preferring ANSI SQL syntax for joins (over mentioning multiple tables in the "from" clause) as once the queries get complex I find the ANSI syntax easier to follow. Using that syntax, joining multiple tables is no big deal. e.g.,
SELECT uploads.<column>, users.<column>, collabs.<column>
FROM tbl_uploads uploads
JOIN tbl_users users ON users.user_id=uploads.user_id
JOIN tbl_collabs collabs ON collabs.file=uploads.file
ORDER BY uploads.date DESC
(Note, replace <column> above with the names of columns you want to select from the respective tables, using AS syntax to provide unique names where necessary.)
Consider that you will probably want to create indexes over the fields in the join conditions for performance if you expect the database will become large. You may also want to use left joins when joining, e.g., tbl_collabs if it is possible an upload will have no collaborators, otherwise the query will return no data if there are no matching rows in tbl_collabs.
The first thing to do is to normalize your data. If you look closely, username appears in all three tables. It shouldn't. It belongs only in the users table. Then your other tables need to have a user_id field instead of the username.
tbl_uploads
|//**id**//|int(10)|No|
|file|varchar(100)|No|
|type|varchar(30)|No|
|size|int(11)|No|
|user_id|int(11)|No|
tbl_collab
|//**id**//|int(11)|No|
|user_id|int(11)|No|
|file|varchar(255)|No|
In both cases the user_id is a foreign key to the id field in the users table. Now we have something consistent to join on.
SELECT * FROM tbl_uploads
INNER JOIN tbl_users ON tbl_uploads.user_id = tbl_users.user_id
INNER JOIN tbl_collab ON tbl_collab.file = tbl_uploads.file
Whether you should use INNER JOIN or LEFT JOIN depends on exactly what you need to do with your data, but INNER JOIN seems more appropriate based on information provided.
Update: As #drew pointed out, none of your tables have a column named date did you perhaps intend to sort by tbl_users.joining_date?
Seems the join is on file to me
SELECT *
FROM tbl_uploads
inner join tbl_users on tbl_uploads.user_id = tbl_users.user_id
inner join tbl_collab on tbl_collab.file = tbl_uploads.file
ORDER BY date DESC
You can just add another join condition. Also, note that implicit joins (having multiple tables in the from clause) isn't considered a good practice, and you should probably use explicit join clauses:
SELECT *
FROM tbl_uploads up
JOIN tbl_users us ON up.user_id = us.user_id
JOIN tbl_collab c ON c.user_id = up.user_id
ORDER BY date DESC
I have a database with 22 tables most tables have a few column fields with identical names. When I use INNER JOIN on the tables with the duplicate column names it will ignore them in the last table. Right now I am only joining 3 tables
SELECT * FROM company C
INNER JOIN typeofdealer PI ON C.CompanyID = PI.CompanyID
INNER JOIN typeofservices TS ON PI.CompanyID = TS.CompanyID
So in this example typeofdealer and typeofservices both contain column names Other and OtherText When I get this query back I only see one Other and one OtherText.
I just discovered as I was writing this that if I do the query in "phpmyadmin" that I get it back exactly as intended. I am doing this query using prepared statements in php and outputting the results using:
echo "<PRE>";
print_r($results);
echo "</PRE>";
I believe the problem is that php arrays cannot contain duplicate fields so is there a way to circumvent the issue I am having?
The workaround you can do for this is to use an alias AS to make a distinction between columns with the same names. Something like:
SELECT PI.Other AS Other1, PI.OtherText AS OtherText2, TS.Other AS Other2, TS.OtherText AS OtherText2 FROM company C
INNER JOIN typeofdealer PI ON C.CompanyID = PI.CompanyID
INNER JOIN typeofservices TS ON PI.CompanyID = TS.CompanyID
Actually it will work the same way if you omit the AS keyword say SELECT PI.Other Other1, PI.OtherText OtherText2
The problem is, as you rightfully suggested, that PHP won't allow multiple entries into an array with the same key name.
The simplest way around this, is to alias the fields in the column selection section of the query, like so:
SELECT *, typeofservices.Other as ServicesOther, typeofservices.OtherText as ServicesOtherText FROM company C
INNER JOIN typeofdealer PI ON C.CompanyID = PI.CompanyID
INNER JOIN typeofservices TS ON PI.CompanyID = TS.CompanyID
It's not pretty but it's simple.
I have three different SQL tables I need to join:
table "internet" with columns id|type|status
table "type_list" with columns id|type_name
table "status_list" with columns id|status_name
I want to output text from the two other tables (type_list, status_list) but not values as numbers which currently I have in table "internet".
I also don't want to make lazy programming - PHP array to make ID's equal to something like
$type_list = array("1"=>"VDSL2","2"=>"ADSL");
$status_list = array("1"=>"Pending","2"=>"Active");
because the text is already in the tables, i just dont know how to join them and output the text as query combined together in one query.
Use JOIN
SELECT i.id, type_name, status_name
FROM internet i
LEFT OUTER JOIN type_list t ON t.id = i.type
LEFT OUTER JOIN status_list s ON s.id= i.status
Read the MySQL doc for more informations.
Just write the select with the fields you want.
select internet.id,type_name,status_name from internet
inner join type_list
on type_list.id=internet.id
inner join status_list
on status_list.id=internet.id
For this you need a LEFT JOIN, like so:
SELECT i.id, t.type_name, s.status_name
FROM internet AS i
LEFT JOIN type_list AS t ON t.id = i.id
LEFT JOIN status_list AS s ON s.id= i.id
From your question, it is unclear what field you would like to join the queries on. In the above example, the queries are joined on the id field.
Please also note that the AS is not actually necessary, I have just put it in there to make it clear what is going on
The default_albums table is used for storing album data.
The default_hottest_categories table is used to store the category
data
The default_album_hc_connect table is used to connect the default_hottest_categories table with the default_albums
table.
I need to be able to display all albums that are apart of the category which is_hottest. the is_hottest column is located in the default_hottest_categories table. The below code is what I have so far:
$q1 = $this->db->query("SELECT * FROM default_albums a, default_hottest_categories d INNER JOIN default_album_hc_connect dc
ON d.id = dc.hottest_categories_id INNER JOIN default_albums ON dc.albums_id = default_albums.album_id
WHERE d.is_hottest = 'Yes'");
I really do not know if this is correct or not. So if you can help me, I'd much appreciate it.
This should work. You had an extra instance of the default_albums table in your FROM clause. I removed that. Also you generally want to join all your tables together. The comma you had in there is used for CROSS JOINS, but is not used that often and is not needed in this case. Also I would recommend only taking the fields you need in your SELECT clause.
SELECT *
FROM default_albums a
INNER JOIN default_album_hc_connect dc
ON a.albums_id = dc.album_id
INNER JOIN default_hottest_categories d
ON dc.hottest_categories_id = d.id
WHERE d.is_hottest = 'Yes'"
I'm having a problem with my SELECT sql statement and I haven't figured it out yet. When I print out the results using mysql_fetch_assoc() function, I get repetitive rows/records. A record is repeated 13 times. I don't know why and I have done it right as far as my knowledge tells me.
The following is my sql query:
SELECT
members.member_id,
members.firstname,
members.lastname,
billing_details.Street_Address,
billing_details.Mobile_No,
orders_details.*,
food_details.*,
categories.*,
cart_details.*,
quantities.*
FROM
members, billing_details, orders_details, categories,
quantities, food_details, cart_details
WHERE
members.member_id=orders_details.member_id AND
billing_details.billing_id=orders_details.billing_id AND
orders_details.cart_id=cart_details.cart_id AND
cart_details.food_id=food_details.food_id AND
cart_details.quantity_id=quantities.quantity_id
You don't have "categories" in your WHERE clause. I am guessing you have 13 categories? If you need a better explanation, let me know.
Use SELECT DISTINCT.
Please Note
Using the mysql_* libraries is bad practise. They are Deprecated and should be replaced by either the mysqli_* libraries or a PDO object.
Why dont you make left Joins like below
SELECT members.member_id, members.firstname, members.lastname, billing_details.Street_Address, billing_details.Mobile_No, orders_details.*, food_details.*, categories.*, cart_details.*, quantities.* FROM members as m
Left join billing_details as b ON b.billing_id=m.?
LEFT JOIN orders_details as o ON o.cart_id=m.?
LEFT JOIN food_details as f ON f.f_id =m.?
LEFT JOIN cart_details as c ON c.?=?
LEFT JOIN quantitiesas q ON q.?=?
LEFT JOIN categories as cat ON cat.?=?
If you only want each member_id to appear once, you can use DISTINCT:
SELECT DISTINCT members.member_id, ...
You can also use JOIN USING to avoid repetition (DRY):
http://dev.mysql.com/doc/refman/5.7/en/join.html (search for USING(column_list))
That way, you'd also have noticed the msising predicate, since it would be right next to the joined table name.