I'm stuck on the inner join scenario for my tables. Can you please help me? What I am doing wrong here?
Here is the scenario that I'm trying to do:
I have billing and shipping country/states columns which I am trying to populate with inner join, but somehow it is not working. Thanks a lot for your help:
$sql = $this->connection->query("SELECT * FROM ".TBL_USERS."
INNER JOIN ".TBL_USER_LEVEL." ON ".TBL_USERS.".userlevel = ".TBL_USER_LEVEL.".user_level_id
INNER JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".country OR ".TBL_USERS.".bcountry = ".TBL_COUNTRIES.".country_id
INNER JOIN ".TBL_STATES." ON ".TBL_USERS.".states OR ".TBL_USERS.".bstates = ".TBL_STATES.".states_id
WHERE ".TBL_USERS.".username = '$username'");
i changed the query to; and the error im gettin is
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'countries'' in
$sql = $this->connection->query("SELECT * FROM ".TBL_USERS."
INNER JOIN ".TBL_USER_LEVEL." ON ".TBL_USERS.".userlevel = ".TBL_USER_LEVEL.".user_level_id
INNER JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".country = ".TBL_COUNTRIES.".country_id
INNER JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".bcountry = ".TBL_COUNTRIES.".country_id
INNER JOIN ".TBL_STATES." ON ".TBL_USERS.".states = ".TBL_STATES.".states_id
INNER JOIN ".TBL_STATES." ON ".TBL_USERS.".bstates = ".TBL_STATES.".states_id
WHERE ".TBL_USERS.".username = '$username'");
OK here is correct syntax thanks a lot to #Tiberiu-IonuČ› Stan
$sql = $this->connection->query("SELECT * FROM ".TBL_USERS."
LEFT JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".country = ".TBL_COUNTRIES.".country_id
LEFT JOIN ".TBL_COUNTRIES." AS ".TBL_COUNTRIES."_b ON ".TBL_USERS.".bcountry=".TBL_COUNTRIES."_b.country_id
INNER JOIN ".TBL_USER_LEVEL." ON ".TBL_USERS.".userlevel = ".TBL_USER_LEVEL.".user_level_id
LEFT JOIN ".TBL_STATES." ON ".TBL_USERS.".states = ".TBL_STATES.".states_id
LEFT JOIN ".TBL_STATES." AS ".TBL_STATES."_b ON ".TBL_USERS.".bstates=".TBL_STATES."_b.states_id
WHERE ".TBL_USERS.".username = '$username'");
You can use OR and AND inside join statements.
I do it all the time.
Here's one that works:
LEFT JOIN `currencies` ON (
`currency_foreign`=`invoice_entry_amount_currency`
AND
`currency_reference`='".$strTransformToCurrency."'
AND
`currency_date`=FLOOR(`invoice_paid_timestamp`/86400)*86400
)
Problem is here:
INNER JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".country = ".TBL_COUNTRIES.".country_id
INNER JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".bcountry = ".TBL_COUNTRIES.".country_id
MySQL can't decide on which relation to join the countries table (because MySQL thinks .country and .countryb can be different - so after join it doesn't know which columns will be returned or used for conditions and ordering).
Try it like this:
INNER JOIN ".TBL_COUNTRIES." ON ".TBL_USERS.".country = ".TBL_COUNTRIES.".country_id
INNER JOIN ".TBL_COUNTRIES." AS ".TBL_COUNTRIES."_b ON ".TBL_USERS.".bcountry=".TBL_COUNTRIES."_b.country_id
In case you have really big tables, do an EXPLAIN with the full final query including conditions and ordering to find out if MySQL is doing a table copy because of "TBL_USERS AS TBL_USERS_B".
You cannot use constructs like JOIN table ON field OR another_field = expression, unless referenced field is of boolean type.
You should use constructs that will return boolean result, in your case something like this:
$sql = $this->connection->query("SELECT * FROM $TBL_USERS
JOIN $TBL_USER_LEVEL ON $TBL_USERS.userlevel = $TBL_USER_LEVEL.user_level_id
JOIN $TBL_COUNTRIES ON $TBL_USERS.country = $TBL_COUNTRIES.country_id
OR $TBL_USERS.bcountry = $TBL_COUNTRIES.country_id
JOIN $TBL_STATES ON $TBL_USERS.states = $TBL_STATES.states_id
OR $TBL_USERS.bstates = $TBL_STATES.states_id
WHERE $TBL_USERS.username = '$username'");
I have also used the variable directly, otherwise lots of string concatenations looks messy.
And your query as is now is open for SQLi.
Related
Please help me out in fetching into rows.
$results = mysqli_query($db, "SELECT base.*, charge.id, cloud.id, mask.id, sense.id.*
FROM base INNER JOIN charge ON base.id = charge.id
INNER JOIN cloud ON base.id = cloud.id
INNER JOIN mask ON base.id = mask.id
INNER JOIN sense ON base.id = sense.id ");
I'm getting an error a {Error: Unknown table 'sense.id'}. Even though there is an error.
How to correct this?
please try sense.* inplace of sense.id.*
"SELECT base.*, charge.id, cloud.id, mask.id, sense.*
FROM base INNER JOIN charge ON base.id = charge.id
INNER JOIN cloud ON base.id = cloud.id
INNER JOIN mask ON base.id = mask.id
INNER JOIN sense ON base.id = sense.id "
I'm having difficulties using the LEFT OUTER JOIN in multiple tables.
My tables are: countries, customer_info, package_types, service_types and shipping_info
This is my code so far:
$sql = "SELECT shipping_info.shipping_id, shipping_info.weight, shipping_info.width, shipping_info.height, shipping_info.length, shipping_info.cost, shipping_info.status,
service_types.service, package_types.package_type, countries1.country AS fromCountry, countries2.country AS toCountry, countries3.country AS resiCountry, customer_info.name, customer_info.address
, customer_info.city, customer_info.postcode, customer_info.zipcode, customer_info.phone, customer_info.email, customer_info.country
FROM shipping_info
LEFT OUTER JOIN service_types ON shipping_info.service_type = service_types.serviceType_id
LEFT OUTER JOIN package_types ON shipping_info.package_type = package_types.packageType_id
LEFT OUTER JOIN customer_info 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";
$statement = $con_db->query($sql);
$result = $statement->fetchAll();
I'm getting a fatal error in my final line and I believe that's because $result is null. But I'm unable to figure out the error.
Appreciate any help.
It may be your query has following manual error:
tablename or fieldname mismatch
The following query always returns #1054 - Unknown column 'T_RELATIF_SESS.REL_COM_ID' in 'on clause'
SELECT
`T_FORMATIONS`.`FOR_ID`,
`T_FORMATIONS`.`FOR_TITRE`,
`T_FORMATIONS`.`FOR_NIVEAU`,
`T_FORMATIONS`.`FOR_MAX_PART`,
`T_RELATIF_SESS`.`REL_COM_ID`,
`T_RELATIF_SESS`.`REL_SES_ID`,
`T_SESSIONS`.`SES_ID`,
`T_SESSIONS`.`SES_TITRE`,
`T_SESSIONS`.`SES_TYPE`,
`T_SESSIONS`.`SES_ADRESSE`,
`T_SESSIONS`.`SES_NPA`,
`T_SESSIONS`.`SES_LIEU`,
`T_SESSIONS`.`SES_PRIX_SPECIAL`,
`T_SESSIONS`.`SES_VAL_PRIX_SPECIAL`,
`T_SESSIONS`.`SES_PRIX_SPEC_EXP`,
`T_SESSIONS`.`SES_SUPP_COURS_INCL`,
`T_SESSIONS`.`SES_SUPP_COURS_ADD`,
`T_SESSIONS`.`SES_PRIX_SUPP_COURS_ADD`,
`T_SESSIONS`.`SES_HORAIRE_SPECIAL`,
`T_SESSIONS`.`SES_REMARQUES`,
`T_SESSIONS`.`SES_REC_ID`,
`T_COURS`.`COU_ID`,
`T_COURS`.`COU_DATE`,
(SELECT `COU_DATE` FROM `T_COURS` WHERE `T_COURS`.`COU_SES_ID` = `T_SESSIONS`.`SES_ID` ORDER BY `COU_DATE` ASC LIMIT 1) AS `PREMIERCOURS`,
(SELECT `COU_DATE` FROM `T_COURS` WHERE `T_COURS`.`COU_SES_ID` = `T_SESSIONS`.`SES_ID` ORDER BY `COU_DATE` DESC LIMIT 1) AS `DERNIERCOURS`
FROM `T_COURS`
INNER JOIN `T_COMMANDES` ON `T_RELATIF_SESS`.`REL_COM_ID` = `T_COMMANDES`.`COM_ID`
INNER JOIN `T_RELATIF_SESS` ON `T_SESSIONS`.`SES_ID` = `T_RELATIF_SESS`.`REL_SES_ID`
INNER JOIN `T_SESSIONS` ON `T_COURS`.`COU_SES_ID` = `T_SESSIONS`.`SES_ID`
INNER JOIN `T_FORMATIONS` ON `T_SESSIONS`.`SES_FOR_ID` = `T_FORMATIONS`.`FOR_ID`
WHERE `T_COMMANDES`.`COM_ID`=19
This query worked fine before I add
INNER JOIN `T_COMMANDES` ON `T_RELATIF_SESS`.`REL_COM_ID` = `T_COMMANDES`.`COM_ID`
INNER JOIN `T_RELATIF_SESS` ON `T_SESSIONS`.`SES_ID` = `T_RELATIF_SESS`.`REL_SES_ID`
And
WHERE `T_COMMANDES`.`COM_ID`=19
T_RELATIF_SESS is juste an associative table between the tables called "T_SESSIONS" and "T_COMMANDES".
I've tried to rewrite the query many times but I still get this error and I really don't understand why. Every field exists in my database.
I know it may be simple but it really gives me headache. Can someone can give me a hand or just explain to me what I do wrong? It would be much apprecietaded!
Thank you very much!
So from your description you try to run the script without
INNER JOIN `T_COMMANDES` ON `T_RELATIF_SESS`.`REL_COM_ID` = `T_COMMANDES`.`COM_ID`
INNER JOIN `T_RELATIF_SESS` ON `T_SESSIONS`.`SES_ID` = `T_RELATIF_SESS`.`REL_SES_ID`
and it is working, but not with that script? Try to make it in order, since on your first inner join, you are trying to join the table (T_COMMANDES) with the table that you will join next (T_RELATIF_SESS).
So try:
INNER JOIN `T_SESSIONS` ON `T_COURS`.`COU_SES_ID` = `T_SESSIONS`.`SES_ID`
INNER JOIN `T_FORMATIONS` ON `T_SESSIONS`.`SES_FOR_ID` = `T_FORMATIONS`.`FOR_ID`
INNER JOIN `T_RELATIF_SESS` ON `T_SESSIONS`.`SES_ID` = `T_RELATIF_SESS`.`REL_SES_ID`
INNER JOIN `T_COMMANDES` ON `T_RELATIF_SESS`.`REL_COM_ID` = `T_COMMANDES`.`COM_ID`
your order of table are messed up after you add your join, since you are using INNER JOIN, you can declare the table anywhere you like as long as the fields are visible on the joins. It will still yield the same result.
To solve the problem, put those new join on the lower part of your joins:
FROM T_COURS
INNER JOIN T_SESSIONS
ON T_COURS.COU_SES_ID = T_SESSIONS.SES_ID
INNER JOIN T_FORMATIONS
ON T_SESSIONS.SES_FOR_ID = T_FORMATIONS.FOR_ID
INNER JOIN T_RELATIF_SESS
ON T_SESSIONS.SES_ID = T_RELATIF_SESS.REL_SES_ID
INNER JOIN T_COMMANDES
ON T_RELATIF_SESS.REL_COM_ID = T_COMMANDES.COM_ID
The reason why an error message: Unknown column 'T_RELATIF_SESS.REL_COM_ID' in 'on clause' was thrown is because when joining T_COURS with T_COMMANDES, column T_RELATIF_SESS.REL_COM_ID isn't visible yet since you have declared table T_RELATIF_SESS on the lower part of the join.
You try to access T_RELATIF_SESS before you have joined the table. You must join T_COMMANDES after T_RELATIF_SESS and T_RELATIF_SESS after T_SESSIONS
SELECT
`T_FORMATIONS`.`FOR_ID`,
...
FROM `T_COURS`
INNER JOIN `T_SESSIONS` ON `T_COURS`.`COU_SES_ID` = `T_SESSIONS`.`SES_ID`
INNER JOIN `T_FORMATIONS` ON `T_SESSIONS`.`SES_FOR_ID` = `T_FORMATIONS`.`FOR_ID`
INNER JOIN `T_RELATIF_SESS` ON `T_SESSIONS`.`SES_ID` = `T_RELATIF_SESS`.`REL_SES_ID`
INNER JOIN `T_COMMANDES` ON `T_RELATIF_SESS`.`REL_COM_ID` = `T_COMMANDES`.`COM_ID`
WHERE `T_COMMANDES`.`COM_ID`=19
I have a nested mysql_query.
$resultSub = mysql_query("SELECT *
FROM ensembles
WHERE en_name = $name
LEFT JOIN ensemble_names on ensembles.en_name = ensemble_names.en_nm_ID
LEFT JOIN students on ensembles.en_stu = students.s_ID
LEFT JOIN part_names on ensembles.en_part = part_names.p_nm_ID
ORDER BY $sort $orderBy");
The query works fine without the WHERE clause, which I thought may be filtering out rows for the LEFT JOIN command, but that's not the case.
The WHERE clause should be placed after the LEFT JOINs:
$resultSub = mysql_query("SELECT *
FROM ensembles
LEFT JOIN ensemble_names on ensembles.en_name = ensemble_names.en_nm_ID
LEFT JOIN students on ensembles.en_stu = students.s_ID
LEFT JOIN part_names on ensembles.en_part = part_names.p_nm_ID
WHERE en_name = $name
ORDER BY $sort $orderBy");
Well, you put the WHERE clause in the wrong place.
Read the documentation.
I have Doctrine2 DQL query but I want to build it with QueryBuilder, I have noticed that produced DQL is somewhat different from the handcrafted one, and I'm wondering what am I missing here - maybe I'm not aware of something or doing things wrong way?
Ok, some details:
My handcrafted query looks like this:
select count(fi.id)
from Entities\Content\FolderLookup fl
join fl.site fls
join fl.folder flf,
Entities\Content\FolderItem fi
join fi.site fis
join fi.folder fif
join fi.item it
join it.type tp
join it.content ic
where fl.namePath = ?1
and tp.name = ?2
and fls.id = fis.id
and flf.id = fif.id
Now, I'm trying to reproduce it like this with QueryBuilder:
$qb->select("count(fi.id)")->from("Entities\Content\FolderLookup", "fl")->join("fl.site","fls")->join("fl.folder", "flf");
$qb->from("Entities\Content\FolderItem","fi")->join("fi.site","fis")->join("fi.folder","fif");
$qb->join("fi.item","it")->join("it.type","tp")->join("it.content","ic");
$wherePart = $qb->expr()->andx();
$wherePart->add($qb->expr()->eq("fl.namePath","?1"));
$wherePart->add($qb->expr()->eq("tp.name","?2"));
$wherePart->add($qb->expr()->eq("fls.id","fis.id"));
$wherePart->add($qb->expr()->eq("flf.id","fif.id"));
$qb->where($wherePart);
This however is producing this DQL query:
SELECT count(fi.id) FROM Entities\Content\FolderLookup fl,
Entities\Content\FolderItem fi
INNER JOIN fl.site fls
INNER JOIN fl.folder flf
INNER JOIN fi.site fis
INNER JOIN fi.folder fif
INNER JOIN fi.item it
INNER JOIN it.type tp
INNER JOIN it.content ic
WHERE (fl.namePath = ?1)
AND (tp.name = ?2)
AND (fls.id = fis.id)
AND (flf.id = fif.id)
As you can see there is part of this missing comapring to handcrafted one (First line):
fl join fl.site fls join fl.folder flf
I'm not sure why these joins are missing as I am defining them here:
$qb->select("count(fi.id)")->from("Entities\Content\FolderLookup", "fl")->join("fl.site","fls")->join("fl.folder", "flf");
Update:
The fun part starts, when DQL gets translated into SQL - in this case MySQL:
Handcrafted one becomes:
SELECT count(f0_.id) AS sclr0 FROM FolderLookup f1_ INNER JOIN Site s2_ ON f1_.site_id = s2_.id INNER JOIN Folder f3_ ON f1_.folder_id = f3_.id, FolderItem f0_ INNER JOIN Site s4_ ON f0_.site_id = s4_.id INNER JOIN Folder f5_ ON f0_.folder_id = f5_.id INNER JOIN Item i6_ ON f0_.item_id = i6_.id INNER JOIN ItemType i7_ ON i6_.type_id = i7_.id INNER JOIN ItemContent i8_ ON i6_.content_id = i8_.id WHERE f1_.namePath = ? AND i7_.name = ? AND s2_.id = s4_.id AND f3_.id = f5_.id
Where generated one looks like this:
SELECT count(f0_.id) AS sclr0 FROM FolderLookup f1_, FolderItem f0_ INNER JOIN Site s2_ ON f1_.site_id = s2_.id INNER JOIN Folder f3_ ON f1_.folder_id = f3_.id INNER JOIN Site s4_ ON f0_.site_id = s4_.id INNER JOIN Folder f5_ ON f0_.folder_id = f5_.id INNER JOIN Item i6_ ON f0_.item_id = i6_.id INNER JOIN ItemType i7_ ON i6_.type_id = i7_.id INNER JOIN ItemContent i8_ ON i6_.content_id = i8_.id WHERE (f1_.namePath = ?) AND (i7_.name = ?) AND (s2_.id = s4_.id) AND (f3_.id = f5_.id)
And this is invalid statement, as database returns with:
Column not found: 1054 Unknown column 'f1_.site_id' in 'on clause'
Any ideas welcome.
It seems the DQL parser is wrongly positioning the joins to the wrong from.
My initial suggestion is to try to make only 1 FROM item and a subselect.
Also, I'd love if you add the same content you asked here in our bug tracking: http://www.doctrine-project.org/jira/browse/DDC
Thanks a lot!
Guilherme Blanco
Doctirne Core Developer
they are not missing. just reordered
INNER JOIN fl.site fls
INNER JOIN fl.folder flf