I have a huge select query where i have to join more than 85 tables. I keep getting an error when running the query, if I re-run the query when shrinking the overall statement it runs fine.
See a portion of the join below, it does that all the way to table 85:
select $imploded_tables from $apps a
left join $mobile_c0 $m_c0 on $apps.id = $m_c0.id
left join $mobile_c1 $m_c1 on $m_c0.id = $m_c1.id
left join $mobile_c2 $m_c2 on $m_c1.id = $m_c2.id
left join $mobile_c3 $m_c3 on $m_c2.id = $m_c3.id
left join $mobile_c4 $m_c4 on $m_c3.id = $m_c4.id
left join $mobile_c5 $m_c5 on $m_c4.id = $m_c5.id
left join $mobile_c6 $m_c6 on $m_c5.id = $m_c6.id
left join $mobile_c7 $m_c7 on $m_c6.id = $m_c7.id
left join $mobile_c8 $m_c8 on $m_c7.id = $m_c8.id
left join $mobile_c9 $m_c9 on $m_c8.id = $m_c9.id
left join $mobile_c10 $m_c10 on $m_c9.id = $m_c10.id
...
...
Mysql Documentation
The maximum number of tables that can be referenced in a single join is 61.
As per #sf_admin answer the maximum no of join is 61 , so you can do something like below
select imploded_tables from apps a
JOIN
(
SELECT * from mobile_c0
UNION
SELECT * from mobile_c1
....
)tmp
where(tmp.id=a.id)
It might not 100% percent answer your question but this is some work around I did
I'm trying to connect to 3 tables using LEFT OUTER JOIN. I'm not sure if I'm doing this correctly.
Tables are: rates, countries and service_types
Query:
$sql = "SELECT rates.rate_id, rates.initial_change, service_types.service, countries.country
FROM rates
LEFT OUTER JOIN service_types ON rates.service_id = service_types.serviceType_id
LEFT OUTER JOIN countries ON rates.from_id = country.country_id
LEFT OUTER JOIN countries ON rates.to_id = country.country_id
ORDER BY service_types.serviceType_id ASC";
$statement = $con_db->exec($sql);
$result = $statement->fetchAll();//error points to this line
This is the error message:
Fatal error: Call to a member function fetchAll() on a non-object in
One thing I noticed is the way your accessing your tables is incorrect. I'm guessing the SQL is invalid, which is returning null from exec. Try changing your query to this:
$sql = "SELECT rates.rate_id, rates.initial_change, service_types.service, countries1.country, countries2.country
FROM rates
LEFT OUTER JOIN service_types ON rates.service_id = service_types.serviceType_id
LEFT OUTER JOIN countries as countries1 ON rates.from_id = countries1.country_id
LEFT OUTER JOIN countries as countries2 ON rates.to_id = countries2.country_id
ORDER BY service_types.serviceType_id ASC";
Note the country changed to countries1 & countries2 in the join condition, and also the columns in the select.
I'm trying to get data from multiple tales using LEFT OUTER JOIN but I'm getting a fatal error.
Table names, field names, db connection are correct.
$sql = "SELECT shipping_info.shipping_id, service1.service, package1.package_type, countries1.country AS fromCountry, countries2.country AS toCountry, countries3.country AS resiCountry, customer1.name,
FROM shipping_info
LEFT OUTER JOIN service_types AS service1 ON shipping_info.service_type = service_types.serviceType_id
LEFT OUTER JOIN package_types AS package1 ON shipping_info.package_type = package_types.packageType_id
LEFT OUTER JOIN customer_info AS customer1 ON shipping_info.customer_id = customer_info.customer_id
LEFT OUTER JOIN countries AS countries1 ON shipping_info.from_loc = countries1.country_id
LEFT OUTER JOIN countries AS countries2 ON shipping_info.to_loc= countries2.country_id
LEFT OUTER JOIN countries AS countries3 ON shipping_info.to_id = countries3.country_id
ORDER BY shipping_info.order_date DESC";
Fatal error: Call to a member function fetchAll() on a non-object in....
try changing your query to this:
SELECT s1.shipping_id,
s1.service,
p1.package_type,
c1.country fromCountry,
c2.country toCountry,
c3.country resiCountry,
c1.name
FROM shipping_info si
LEFT JOIN service_types s1 ON si.service_type = s1.serviceType_id
LEFT JOIN package_types p1 ON si.package_type = p1.packageType_id
LEFT JOIN customer_info c1 ON si.customer_id = c1.customer_id
LEFT JOIN countries c1 ON si.from_loc = c1.country_id
LEFT JOIN countries c2 ON si.to_loc= c2.country_id
LEFT JOIN countries c3 ON si.to_id = c3.country_id
ORDER BY si.order_date DESC;
you had multiple typos in the query itself with incorrect syntax.. also LEFT OUTER JOIN and LEFT JOIN are exactly the same
Also can you post how you are executing this query? you may have an issue with the actual method for executing it.
I'm not a MySQL expert, but this looks wrong. Consider your first join:
LEFT OUTER JOIN service_types AS service1
ON shipping_info.service_type = service_types.serviceType_id
You give table service_types an alias (a correlation name) of service1, but then don't use it in the ON part of the join. The first thing I would try is either get rid of the correlation name:
LEFT OUTER JOIN service_types
ON shipping_info.service_type = service_types.serviceType_id
...or use it:
LEFT OUTER JOIN service_types AS service1
ON shipping_info.service_type = service1.serviceType_id
Since you're using it in the names of the columns you're actually selecting, I'd go with using it in ON part of the join. Whichever, repeat with package_types and customer_info and then try.
Right off the bat I can see that you have an extra comma just before the FROM clause. This would cause an error and could result in the error you are getting as you would be running fetchAll on a non-object, i.e. the query that wasn't formatted properly.
Your table aliases are pretty long, so you could either shorten them or ditch them altogether and just use the full table name.
SELECT
si.shipping_id,
st.service,
pt.package_type,
c1.country AS fromCountry,
c2.country AS toCountry,
c3.country AS resiCountry,
ci.name
FROM shipping_info si
LEFT JOIN service_types st
ON si.service_type = st.serviceType_id
LEFT JOIN package_types pt
ON si.package_type = pt.packageType_id
LEFT JOIN customer_info ci
ON si.customer_id = ci.customer_id
LEFT JOIN countries c1
ON si.from_loc = c1.country_id
LEFT JOIN countries c2
ON si.to_loc= c2.country_id
LEFT JOIN countries c3
ON si.to_id = c3.country_id
ORDER BY si.order_date DESC;
Also, I've recently moved over to using MySQL Workbench. It's definitely worth checking out. I like it better than PHPMyAdmin. It's a better workflow for me and has cool tools like the reverse engineer tool that will build an ERD for you based on your tables. It's great for testing out your queries before using them in your PHP code.
MySQL Workbench
http://www.mysql.com/products/workbench/
Here is the sql query
SELECT * FROM seedbed
LEFT OUTER JOIN fertilizers AS seedfert ON seedfert.fert_protocol =seedbed.seed_protocol
LEFT OUTER JOIN pesticides AS seedpest ON seedpest.pest_protocol = seedbed.seed_protocol
LEFT OUTER JOIN fertilizers_list AS seedfert_list ON seedfert.fert_id =seedfert_list.id
LEFT OUTER JOIN pesticides_list AS seedpest_list ON seedpest.pest_id = seedpest_list.id
LEFT OUTER JOIN field ON field.field_protocol = seedbed.seed_protocol + "%"
LEFT OUTER JOIN fertilizers AS fieldfert ON fieldfert.fert_protocol = field.field_protocol
LEFT OUTER JOIN pesticides AS fieldpest ON fieldpest.pest_protocol = field.field_protocol
LEFT OUTER JOIN stock ON stock.field_protocol = field.field_protocol
LEFT OUTER JOIN fertilizers_list AS fieldfert_list ON fieldfert.fert_id =fieldfert_list.id
LEFT OUTER JOIN pesticides_list AS fieldpest_list ON fieldpest.pest_id = fieldpest_list.id
WHERE seedbed.seed_protocol LIKE "1/2013/2%"
ORDER BY field_num;
In php is exactly the same i use codeigniter but i dont use for this active record library so is pretty much the same.
$sql = "SELECT * FROM seedbed
LEFT OUTER JOIN fertilizers AS seedfert ON seedfert.fert_protocol = seedbed.seed_protocol
LEFT OUTER JOIN pesticides AS seedpest ON seedpest.pest_protocol = seedbed.seed_protocol
LEFT OUTER JOIN fertilizers_list AS seedfert_list ON seedfert.fert_id = seedfert_list.id
LEFT OUTER JOIN pesticides_list AS seedpest_list ON seedpest.pest_id = seedpest_list.id
LEFT OUTER JOIN field ON field.field_protocol = seedbed.seed_protocol + '%'
LEFT OUTER JOIN fertilizers AS fieldfert ON fieldfert.fert_protocol = field.field_protocol
LEFT OUTER JOIN pesticides AS fieldpest ON fieldpest.pest_protocol = field.field_protocol
LEFT OUTER JOIN stock ON stock.field_protocol = field.field_protocol
LEFT OUTER JOIN fertilizers_list AS fieldfert_list ON fieldfert.fert_id =fieldfert_list.id
LEFT OUTER JOIN pesticides_list AS fieldpest_list ON fieldpest.pest_id = fieldpest_list.id
WHERE seedbed.seed_protocol LIKE '".$this->db->escape_like_str($ins_protocol)."%'
ORDER BY field_num";
$query = $this->db->query($sql);
$data = $query->result();
print_r($data);
The problem now is that in sql server i get all the results i should get although in php i dont get the results of my first two JOINS. And i have no idea why?
I hope someone knows whats going on.
As alluded to by the OP, the issue is most likely to do with having the same field names in multiple tables, therefore they will get combined/overwritten when executed and returned in PHP.
Solution is to give all fields/columns that have conflicting names unique aliases. I can't think of a way to do this automatically unfortunately, so I think it would have to be a manual process.
There could also be issues with how the tables are grouped, so just in case I'll throw in a bunch of parentheses!
SELECT seedbed.*,
seedfert.field1 AS seedfert_field1, seedfert.field2 AS seedfert_field2,
seedpest.field1 AS seedpest_field1, seedpest.field2 AS seedpest_field2,
seedfert_list.field1 AS seedfert_list_field1, seedfert_list.field2 AS seedfert_list_field2,
seedpest_list.field1 AS seedpest_list_field1, seedpest_list.field2 AS seedpest_list_field2,
etc...
FROM (((((((((seedbed
LEFT OUTER JOIN fertilizers AS seedfert ON seedfert.fert_protocol = seedbed.seed_protocol)
LEFT OUTER JOIN pesticides AS seedpest ON seedpest.pest_protocol = seedbed.seed_protocol)
LEFT OUTER JOIN fertilizers_list AS seedfert_list ON seedfert.fert_id = seedfert_list.id)
LEFT OUTER JOIN pesticides_list AS seedpest_list ON seedpest.pest_id = seedpest_list.id)
LEFT OUTER JOIN field ON field.field_protocol = seedbed.seed_protocol + '%')
LEFT OUTER JOIN fertilizers AS fieldfert ON fieldfert.fert_protocol = field.field_protocol)
LEFT OUTER JOIN pesticides AS fieldpest ON fieldpest.pest_protocol = field.field_protocol)
LEFT OUTER JOIN stock ON stock.field_protocol = field.field_protocol)
LEFT OUTER JOIN fertilizers_list AS fieldfert_list ON fieldfert.fert_id =fieldfert_list.id)
LEFT OUTER JOIN pesticides_list AS fieldpest_list ON fieldpest.pest_id = fieldpest_list.id
WHERE seedbed.seed_protocol LIKE '".$this->db->escape_like_str($ins_protocol)."%'
ORDER BY field_num
In Codeigniter, run:
echo $this->db->last_query();
and compare to your non-CI query
Check for NULLs throughout your database that might cause problems with the joins. Other people have also had issues with PHP returning strange results as a result of NULL handling.
this works on me:
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_WARNINGS ON
SET ANSI_PADDING ON
Ok I have 5 tables in my database they are as follows
officelocations_tbl
state_tbl
city_tbl
staff_tbl
titles_tbl
The titles table is only associated with the staff table but the others are all inner joined. I have tried various mysql statements but none are allowing me to bring in the titles_tbl.
here is the latest version of the sql statement I am attempting to use:
SELECT officelocations_tbl.*,city_tbl.*, state_tbl.* , titles_tbl.*,
contact1.firstName AS c1Firstname, contact1.lastName AS c1lastName,
contact1.middleInitial AS c1middleInitial, contact1.suffix AS c1suffix,
contact1.accredations AS c1accredations, contact1.phone AS c1Phone,
contact1.faxNumber AS c1FaxNumber, contact1.mobilePhone AS c1Mobile,
contact1.email AS c1Email, contact1.titleID AS c1Title,
contact2.firstName AS c2Firstname, contact2.lastName AS c2lastName,
contact2.middleInitial AS c2middleInitial, contact2.suffix AS c2suffix,
contact2.accredations AS c2accredations, contact2.phone AS c2Phone,
contact2.faxNumber AS c2FaxNumber, contact2.mobilePhone AS c2Mobile,
contact2.email AS c2Email, contact2.titleID AS c2Title,
partner.firstName AS c3Firstname, partner.lastName AS c3lastName,
partner.middleInitial AS c3middleInitial, partner.suffix AS c3suffix,
partner.accredations AS c3accredations, partner.phone AS c3Phone,
partner.faxNumber AS c3FaxNumber, partner.mobilePhone AS c3Mobile,
partner.email AS c3Email, partner.titleID AS c3Title
FROM officelocations_tbl
JOIN city_tbl ON (officelocations_tbl.cityID = city_tbl.cityID)
INNER JOIN titles_tbl ON titles_tbl.titleID = staff_tbl.titleID
LEFT OUTER JOIN state_tbl ON (officelocations_tbl.stateID = state_tbl.stateID)
LEFT OUTER JOIN staff_tbl contact1 ON (contact1.staffID = officelocations_tbl.contact1)
LEFT OUTER JOIN staff_tbl contact2 ON (contact2.staffID = officelocations_tbl.contact2)
LEFT OUTER JOIN staff_tbl partner ON (partner.staffID = officelocations_tbl.partner)
However this gives me an error [Err] 1054 - Unknown column 'staff_tbl.titleID' in 'on clause'. If I remove both the lines:
INNER JOIN titles_tbl ON titles_tbl.titleID = staff_tbl.titleID
titles_tbl.*,
it works but doesn't pull in the title. I have tried doing it this way as well but then it only pulls in the title once and not for all three contacts.
SELECT
staff_tbl.staffID,
staff_tbl.staffID_C2,
staff_tbl.staffID_P,
staff_tbl.firstName,
staff_tbl.middleInitial,
staff_tbl.lastName,
staff_tbl.suffix,
staff_tbl.accredations,
staff_tbl.email,
staff_tbl.phone,
staff_tbl.mobilePhone,
staff_tbl.officePhone,
staff_tbl.faxNumber,
staff_tbl.address1,
staff_tbl.address2,
staff_tbl.cityID,
staff_tbl.stateID,
staff_tbl.zipCode,
staff_tbl.titleID,
staff_tbl.locationID,
staff_tbl.photoURL,
staff_tbl.vCardURL,
staff_tbl.qRCodeURL,
staff_tbl.resumeURL,
staff_tbl.biography,
staff_tbl.dateCreated,
officelocations_tbl.locationID,
officelocations_tbl.officeName,
officelocations_tbl.address1,
officelocations_tbl.address2,
officelocations_tbl.cityID,
officelocations_tbl.stateID,
officelocations_tbl.zipCode,
officelocations_tbl.officePhone,
officelocations_tbl.contact1,
officelocations_tbl.contact2,
officelocations_tbl.partner,
city_tbl.cityID,
city_tbl.cityName,
state_tbl.stateID,
state_tbl.state_abreviation,
state_tbl.state_name,
titles_tbl.titleID,
titles_tbl.titleName,
contact1.firstName AS c1Firstname, contact1.lastName AS c1lastName,
contact1.middleInitial AS c1middleInitial, contact1.suffix AS c1suffix,
contact1.accredations AS c1accredations, contact1.phone AS c1Phone,
contact1.faxNumber AS c1FaxNumber, contact1.mobilePhone AS c1Mobile,
contact1.email AS c1Email, contact1.titleID AS c1Title,
contact2.firstName AS c2Firstname, contact2.lastName AS c2lastName,
contact2.middleInitial AS c2middleInitial, contact2.suffix AS c2suffix,
contact2.accredations AS c2accredations, contact2.phone AS c2Phone,
contact2.faxNumber AS c2FaxNumber, contact2.mobilePhone AS c2Mobile,
contact2.email AS c2Email, contact2.titleID AS c2Title,
partner.firstName AS c3Firstname, partner.lastName AS c3lastName,
partner.middleInitial AS c3middleInitial, partner.suffix AS c3suffix,
partner.accredations AS c3accredations, partner.phone AS c3Phone,
partner.faxNumber AS c3FaxNumber, partner.mobilePhone AS c3Mobile,
partner.email AS c3Email, partner.titleID AS c3Title
FROM officelocations_tbl
INNER JOIN staff_tbl ON staff_tbl.staffID = officelocations_tbl.contact1
INNER JOIN state_tbl ON state_tbl.stateID = officelocations_tbl.stateID
INNER JOIN titles_tbl ON titles_tbl.titleID = staff_tbl.titleID
INNER JOIN city_tbl ON city_tbl.cityID = officelocations_tbl.cityID
LEFT OUTER JOIN staff_tbl contact1 ON (contact1.staffID = officelocations_tbl.contact1)
LEFT OUTER JOIN staff_tbl contact2 ON (contact2.staffID = officelocations_tbl.contact2)
LEFT OUTER JOIN staff_tbl partner ON (partner.staffID = officelocations_tbl.partner)
This will only pull for the first association of staff_tbl.staffID = officelocations_tbl.contact1. I am stumped as to what to try next. Is there anyone who would know how to get it to pull all 5 tables?
You just need to move your INNER JOIN down lower, e.g. from
INNER JOIN titles_tbl ON titles_tbl.titleID = staff_tbl.titleID
LEFT OUTER JOIN state_tbl ON (officelocations_tbl.stateID = state_tbl.stateID)
to
LEFT OUTER JOIN state_tbl ON (officelocations_tbl.stateID = state_tbl.stateID)
INNER JOIN titles_tbl ON titles_tbl.titleID = staff_tbl.titleID
At the time the parser reaches the INNER JOIN, staff_tbl has not yet been joined, and the parser will not "look ahead" to see if it's joined later. So it immediately bails with a "no such table/field".
Switching the order in which this occurs allows taff_table to be joined in first, and then you can use it in further joins.