Mysql left outer join column does not exist - CodeIgniter DataMapper ORM - php

I'm running the following query, which is being generated by CodeIgniter's DataMapper ORM as I try to query a deep relationship of the form order_product/order/order_status:
SELECT `order_products`.*
FROM (`order_products`)
LEFT OUTER JOIN `orders` orders ON `orders`.`id` = `order_products`.`order_id`
LEFT OUTER JOIN `order_statuses` order_order_statuses ON `order_order_statuses`.`id` = `orders`.`order_status_id`
WHERE `order_products`.`sku` IN ('SYB-SAMPLETEST8', 'Copy of SYB-SAMPLE#B')
AND `order_products`.`deleted` = 0
AND `orders`.`ext_created_on` >= '2014-05-05'
AND `order_products`.`deleted` = 0
AND `orders`.`ext_created_on` <= '2014-05-21'
AND `orders`.`deleted` = 0
AND `order_statuses`.`deleted` = 0
AND `order_order_statuses`.`sales_data` = 1
I'm receiving the following error:
ERROR 1054 (42S22): Unknown column 'order_statuses.deleted' in 'where clause'
My schema for order_statuses table is as follows:
+-------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ext_id | int(11) | YES | | NULL | |
| ext_type_id | int(11) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| sales_data | tinyint(1) | YES | | 0 | |
| deleted | tinyint(1) | NO | | 0 | |
| created_on | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------------+--------------+------+-----+-------------------+----------------+
Why am I receiving this error even though the deleted column exists?

Because You are aliasing it to order_order_statuses.

Related

MariaDB JOIN fails with 1054 Column not found, but FROM...WHERE from two tables works?

I am using PDO and ran into a strange issue with JOIN vs. the alternate syntax.
PHP version: PHP 7.1.7
The PDO module is for PHP7
MariaDB: 5.5.56-MariaDB-1ubuntu0.14.04.1
When I run this:
SELECT *
FROM ShowsSetlists
JOIN Songs ON Songs.SongID = ShowsSetlists.SongID
WHERE ShowsSetlists.SongID = :id
With array('id' => $songID); as the parameter, where $songID is int(28) for example. But I get this error:
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ShowsSetlists.ShowID' in 'on clause'
However, if I run the same exact query (case and all identical) on both HeidiSQL on Windows-side (the DB is in Vagrant ubuntu/trusty32) and within the MySQL console on the Vagrant box, the above query works just fine - no errors and the result is normal.
The same PDOException happens with an alias:
SELECT *
FROM ShowsSetlists
JOIN Songs AS s ON s.SongID = ShowsSetlists.SongID
WHERE ShowsSetlists.SongID = :id
Now, if I build the query with the alternate syntax:
SELECT *
FROM ShowsSetlists sl, Songs s
WHERE
sl.SongID = s.SongID
AND sl.ShowID = :id
Then it works and no PDOException is thrown.
Correct me if I'm wrong, but aren't those two queries basically the same? Why the first one causes a PDOException?
I checked these questions, but they're not really related:
Column not found: 1054 Unknown column using join
join two tables, error 1054 unknown column in 'on clause'
The DB tables:
MariaDB [vortech]> DESCRIBE ShowsSetlists;
+--------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+----------------+
| SetlistID | int(11) | NO | PRI | NULL | auto_increment |
| ShowID | int(11) | YES | MUL | NULL | |
| SongID | int(11) | YES | MUL | NULL | |
| SetlistOrder | int(11) | YES | | NULL | |
+--------------+---------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
MariaDB [vortech]> DESCRIBE Songs;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| SongID | int(11) | NO | PRI | NULL | auto_increment |
| Title | varchar(255) | YES | | NULL | |
| Duration | int(11) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
MariaDB [vortech]> DESCRIBE Shows;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| ShowID | int(11) | NO | PRI | NULL | auto_increment |
| ShowDate | datetime | YES | | NULL | |
| CountryCode | varchar(2) | YES | | NULL | |
| Country | varchar(100) | YES | | NULL | |
| City | varchar(100) | YES | | NULL | |
| Venue | varchar(200) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

What is the best way to update a one table from another in SQL?

I have 2 tables the first one is the product-page visited
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| idproduct | varchar(128) | YES | | NULL | |
| logdate | date | YES | | NULL | |
| idmagasin | int(20) | YES | | NULL | |
| idenseigne | int(20) | YES | | NULL | |
| commanded | int(2) | YES | | 0 | |
+------------+--------------+------+-----+---------+----------------+
And the second one is the product commanded
+-------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| idproduct | varchar(255) | NO | | NULL | |
| idenseigne | int(11) | NO | | NULL | |
| idmagasin | int(11) | NO | | NULL | |
| ingredients | tinytext | YES | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------------+--------------+------+-----+-------------------+----------------+
How can i update the column commanded in product_visited , if product_visited.idproduct = product_commanded.idproduct and product_visited.logdate = product_commanded.date
i'm confused to use inner join or exists
I want to update product_visited.commanded = 1 when the value of logdate and idproduct exists in product_commanded, it will mean the product visited is commanded too
I believe this is what you are looking for:
Update product_visited pv
set commanded = 1
Where exists (Select 1
from product_commanded pc
where pv.idproduct = pc.idproduct and pv.logdate = pc.date
);
Ok, I've made guesses with the join fields but you're after something like this;
UPDATE pv
SET pv.Commanded = 1
FROM Product_Visited pv
JOIN Product_Commanded pc
ON pv.logdate = pc.date
AND pv.idproduct = pc.id
The inner join means that you're only going to update records in Product_Visited where there are matching rows in Product_Commanded based on the join predicates you give it.
Note: this is a SQL Server answer. May or may not work in MySQL
Sounds like you want to update commanded whenever a record exists for same product in commanded table?
in any database:
Update product_visited set commanded = 1
Where exists(Select * from product_commanded
where product_id = product_visited.Product_id)

Eloquent IF clause - always returns true

I am using Entrust's default table structure:
permissions table:
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | UNI | NULL | |
| display_name | varchar(255) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
| created_at | timestamp | NO | | NULL | |
| updated_at | timestamp | NO | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
permission_role table:
+---------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+-------+
| permission_id | int(10) unsigned | NO | PRI | NULL | |
| role_id | int(10) unsigned | NO | PRI | NULL | |
+---------------+------------------+------+-----+---------+-------+
roles table:
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | UNI | NULL | |
| display_name | varchar(255) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
| created_at | timestamp | NO | | NULL | |
| updated_at | timestamp | NO | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
Now, given a role_id I'd like to get select the following from this database:
permissions.id
permissions.display_name
whether the permission_role table contains an entry with the permission_id and the given role_id
The last one turned out to be a bit tricky in Eloquent.
This SQL query accomplishes exactly what I need (ID is obviously replaced by a valid role ID):
SELECT p.id, p.display_name, IF(pr.role_id = ID, 1, 0) AS has_role
FROM permissions p
LEFT OUTER JOIN permission_role pr ON p.id = pr.permission_id;
Example output:
+----+--------------+----------+
| id | display_name | has_role |
+----+--------------+----------+
| 1 | Edit users | 1 |
| 2 | View users | 0 |
| 3 | Delete users | 0 |
+----+--------------+----------+
Can anyone help me out here, on how to do this using Eloquent?
I've tried this, but it always returns 1 (true) in the third column, unlike the SQL query (as seen above).
$result = DB::table('permissions')
->leftJoin('permission_role', 'permission_role.permission_id', '=', 'permission_role.role_id')
->select(DB::raw('permissions.id, permissions.display_name, IF(permission_role.role_id = ID, 1, 0) AS has_role'))
->get();
Ideally, I'd like to do this without using DB::raw, although it is completely fine if that is what it takes.
Thanks in advance for any help!
Structurally, the Query Builder query you've shown looks fine.
What does not look fine is the left join. Shouldn't this:
->leftJoin('permission_role', 'permission_role.permission_id', '=', 'permission_role.role_id')
be this:
->leftJoin('permission_role', 'permission_role.permission_id', '=', 'permissions.id')
?

Get hasMany relationship with Eloquent Laravel

I have two tables with this schmea:
mysql> show columns from table_1;
+-------------+------------------+------+-----+---------------------+-----------
| Field | Type | Null | Key | Default | Extra
+-------------+------------------+------+-----+---------------------+-----------
| id | int(10) unsigned | NO | PRI | NULL | auto_incre
| id_world | int(11) | NO | | NULL |
| key | varchar(255) | NO | | NULL |
| name | varchar(255) | NO | | NULL |
| description | varchar(255) | NO | | NULL |
| level | int(11) | NO | | 0 |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 |
+-------------+------------------+------+-----+---------------------+-----------
8 rows in set (0.00 sec)
and
mysql> show columns from table_2;
+--------------+------------------+------+-----+---------------------+----------
------+
| Field | Type | Null | Key | Default | Extra
|
+--------------+------------------+------+-----+---------------------+----------
| id | int(10) unsigned | NO | PRI | NULL | auto_incr
| key | varchar(255) | NO | | NULL |
| level | int(11) | NO | | NULL |
| name | varchar(255) | NO | | NULL |
| description | varchar(255) | NO | | NULL |
| price | int(11) | NO | | NULL |
| amount | int(11) | NO | | NULL |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 |
+--------------+------------------+------+-----+---------------------+----------
30 rows in set (0.00 sec)
I want to get all fields "from table_2 where table_2.key = table_1.key AND table_2.level = 10" is this the right way with the hasMany option in my model?
my normal query looks like this:
SELECT A.key AS p_key,
A.name AS p_key,
A.description AS p_desc,
A.level AS p_level,
B.key AS r_key,
B.level AS r_level,
B.name AS r_name,
B.description AS r_desc
FROM
table_1 AS A,
table_2 AS B
WHERE
B.key = A.key AND
B.level = '1'
To build hasMany relationship using those tables, you need to create two models first, for example:
class TableOne extends Eloquent {
protected $table = 'table_1';
public function tableTwoItems()
{
return $this->hasMany('TableTwo', 'table_2.key', 'table_1.key')
->where('table_2.level', 1);
}
}
class TableTwo extends Eloquent {
protected $table = 'table_2';
}
Once you created these models in your app/models directory then you may use something like this:
$result = TableOne::with('tableTwoItems')->get();
To select the items/fields, you may use something like this:
$result = TableOne::with(array('tableTwoItems' => function($query){
$query->select('table_2.key as k2', 'table_2.name as name2', 'more...');
}))->select('table_1.key as k1', 'table_1.name as name1', 'more...')->get();
You may access them like:
$result->first()->tableTwoItems->first();
Or you may loop $result and also you may loop the related items using nested loop. For example:
foreach($result as $tableOneItem)
echo $tableOneItem->name;
foreach($tableOneItem->tableTwoItems as $tabletwoItem)
echo $tabletwoItem->name;
endforeach;
endforeach;
Try to use different field names in both table's key and make them unique as well. Read the Eloquent Relation documentation for more.

Sub-query doesn't work

Here's my schema:
Table "Questoes";
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| id_quest | int(11) | NO | | NULL | |
| questao | varchar(255) | NO | | NULL | |
| nivel | int(11) | NO | | NULL | |
| tipo | varchar(255) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+
Table "Respostas";
+----------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| id_quest | int(11) | NO | | NULL | |
| resposta | varchar(255) | NO | | NULL | |
| r_valido | enum('0','1') | NO | | NULL | |
+----------+---------------+------+-----+---------+----------------+
My query is:
SELECT q.questao, r.resposta
FROM questoes q, respostas r
WHERE q.id_quest IN (19,20,21)
AND q.id_quest=r.id_quest
AND r.r_valido = ( SELECT resposta FROM respostas WHERE r_valido= 1 )
What I need is the field questao from table Questoes and the field resposta from table respostas where field r_valido = 1.
The field resposta have 4 results, and only one is valid, in other words, where the field r_valido = 1.
Your query should look like this:
SELECT q.questao, r.resposta FROM questoes AS q JOIN respostas AS r ON r.id_quest = q.id_quest WHERE q.id_quest IN (19,20,21) AND r.r_valido = "1"
Also I found out what is causing that weird error when you use 1 instead of "1" in the query:
We strongly recommend that you do not use numbers as enumeration
values, because it does not save on storage over the appropriate
TINYINT or SMALLINT type, and it is easy to mix up the strings and the
underlying number values (which might not be the same) if you quote
the ENUM values incorrectly
I didn't understood you completely but i think this is what you looking for:
SELECT q.questao, r.resposta
FROM questoes as q
INNER JOIN respostas as r
ON q.id_quest=r.id_quest
WHERE
q.id_quest IN (19,20,21) AND
r.r_valido = '1'

Categories