Codeigniter INNER JOIN with multiple ON [duplicate] - mysql

I want to select data from my database table with join query, but my it doesn't work.
My query:
$this->db->select();
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->join('schedule', 'schedule.itemtype = 'testitem'');
$this->db->where('we.isActive','Y');
This line makes problem with schedule.itemtype = 'testitem':
$this->db->join('schedule', 'schedule.itemtype = 'testitem'');
How can I solve this?

You don't need to join same table twice.
But just to extend ON clause:
$this->db->select();
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid AND schedule.itemtype = \'testitem\'');
$this->db->where('we.isActive','Y');

try
$this->db->select();
$this->db->from("we");
$this->db->join("schedule", "schedule.itemid = we.cid");
$this->db->where("schedule.itemtype","testitem");
$this->db->where("we.isActive","Y");

I believe there are two problems here. The first problem is that you are using one too many quotes in the second join line in your query:
You have: $this->db->join('schedule', 'schedule.itemtype='testitem''); < extra quote
It should be: $this->db->join('schedule', 'schedule.itemtype=testitem');
Second problem: your join doesnt make sense.
Your statement:
$this->db->select();
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->join('schedule', 'schedule.itemtype = testitem');
$this->db->where('we.isActive','Y');
Translates to:
SELECT * FROM we
JOIN schedule ON schedule.itemid = we.cid
JOIN schedule ON schedule.itemtype = testitem
WHERE we.isActive = Y
As you can see you are joining the same table twice on different lines, not only that but what table does "testitem" belong to? We are left to assume that you perhaps want the join where itemtype = testitem which will mean this:
SELECT * FROM we
JOIN schedule ON schedule.itemid = we.cid
WHERE schedule.itemtype = testitem
AND we.isActive = Y
Therefore your final Codeigniter query should be:
$this->db->select('*');
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->where('schedule.itemtype', 'testitem');
$this->db->where('we.isActive','Y');

This will work:
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->where('we.isActive','Y');
$this->db->where('schedule.itemtype', 'testitem');
$this->db->get('we');

$this->db->query('select we_tbl.c_name from we we_tbl,schedule sch_tbl where sch_tbl.itemid = we_tbl.cid AND we_tbl.idActive = '.$activeData);
Try this query according to your problem this could get the data you need.
I've tested on different database but i tried to perform what you're trying to get. https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_in
select
pro_tbl.ProductName,
cat_tbl.CategoryName ,
sup_tbl.SupplierName
from
Products pro_tbl,
Suppliers sup_tbl,
Categories cat_tbl
where
pro_tbl.SupplierID = sup_tbl.SupplierID AND
pro_tbl.CategoryID = cat_tbl.CategoryID;

Two possible problems, depending on what your desired outcome is:
If you need to make two joins and are getting an error with the second join clause, try using double quotes to enclose the constant value on the condition or you'll get a parse error:
$this->db->join('schedule', 'schedule.itemtype = "testitem"');
If you need to join only once with multiple conditions, use parentheses:
$this->db->select('*');
$this->db->from('we');
$this->db->join('schedule', '(schedule.itemid = we.cid AND schedule.itemtype="testitem")');
$this->db->where('we.isActive','Y');
You query is equivalent to writing:
select * from we
inner join schedule on schedule.itemid = we.cid
inner join schedule on schedule.itemtype = "testitem"
where we.isActive = 'Y'
but what you seem to need is
select * from we
inner join schedule on (schedule.itemid = we.cid AND schedule.itemtype = "testitem")
where we.isActive = 'Y'
On your original query, you are doing two joins. In the latter, you'll do only one with multiple conditions.

Related

Magento 2 filterBuilder left join

I'm trying to filter product collection with multiple OR filter with this code :
$values = ['xxx','xxx'];
$filters = [];
$filters[] = $this->_filterBuilder
->setField('field_a')->setConditionType('in')
->setValue($values)
->create();
$filters[] = $this->_filterBuilder
->setField('field_b')
->setConditionType('in')
->setValue($values)
->create();
// two more filter like that
$filterGroup = $this->_filterGroupBuilder
->setFilters($filters)
->create();
$searchCriteria = $this->_searchCriteriaBuilder
->setFilterGroups([$filterGroup])
->create();
$products = $this->_productRepository->getList($searchCriteria)->getItems();
Problem is collection return 0 result instead of two. After analyze sql query generated by Magento eav table are joined with INNER JOIN like that :
INNER JOIN `catalog_product_entity_text` AS `at_field_b` ON (`at_field_b`.`row_id` = `e`.`row_id`) AND (`at_field_b`.`attribute_id` = '204') AND (`at_field_b`.`store_id` = 0)
If on raw sql query I execute it by replacing INNER JOIN by LEFT JOIN it works, i've got my results.
So my question is how can I "force" magento to left join instead of inner ? Or maybe it's a pure coincidence and real reason isn't the left/inner join
I didn't precise but field_a,field_b,etc... aren't not required so they could be empty for products

Cannot use alias from SELECT clause in the WHERE clause

USE stormtrooper_java;
SELECT imperial_battlegroup.BGID, imperial_battlegroup.Designation, imperial_battlegroup.HQ_LocationX, imperial_battlegroup.HQ_LocationY,
stormtrooper_unit.STUID, stormtrooper_unit.UnitCmd, stormtrooper_unit.UnitType, stormtrooper_unit.Location_X, stormtrooper_unit.Location_Y,
ABS(stormtrooper_unit.Location_X - stormtrooper_unit.Location_Y) AS XYRange
from imperial_battlegroup inner join
stormtrooper_unit
on imperial_battlegroup.BGID = stormtrooper_unit.UnitCmd
WHERE Designation = 'Battle Group I' and UnitType = 'Aslt Infantry' AND
XYRange > 100;
When I execute the file without XYRange > 100 it works very well, but I do need that filtering logic in the query.
How can I adjust my query to filter the results by this calculated condition?
SQL does not allow you to use column aliases in WHERE clauses. It does extend the HAVING, so one solution is:
SELECT bg.BGID, bg.Designation, imperial_battlegroup.HQ_LocationX, bg.HQ_LocationY,
u.STUID, u.UnitCmd, u.UnitType, u.Location_X, u.Location_Y,
ABS(stormtrooper_unit.Location_X - stormtrooper_unit.Location_Y) AS XYRange
from imperial_battlegroup bg inner join
stormtrooper_unit
on bg.BGID = u.UnitCmd
WHERE Designation = 'Battle Group I' and UnitType = 'Aslt Infantry'
HAVING XYRange > 100;
Another option is to repeat the expression in the WHERE.
Try this:
SELECT imperial_battlegroup.BGID, imperial_battlegroup.Designation,
imperial_battlegroup.HQ_LocationX, imperial_battlegroup.HQ_LocationY,
stormtrooper_unit.STUID, stormtrooper_unit.UnitCmd,
stormtrooper_unit.UnitType, stormtrooper_unit.Location_X,
stormtrooper_unit.Location_Y,
ABS(stormtrooper_unit.Location_X - stormtrooper_unit.Location_Y) AS XYRange
from imperial_battlegroup inner join
stormtrooper_unit
on imperial_battlegroup.BGID = stormtrooper_unit.UnitCmd
WHERE Designation = 'Battle Group I' and UnitType = 'Aslt Infantry' AND
ABS(stormtrooper_unit.Location_X - stormtrooper_unit.Location_Y) > 100;
Just updated the last line, rest everything is same.
Its forbidden to use alias in where clause. So use the function itself
where ABS(stormtrooper_unit.Location_X - stormtrooper_unit.Location_Y)> 100

How to use "MAX" in codeigniter where?

There is $this->db_selec_max(); for select max element from row set in select but I want to use max in where. How to use "MAX" in codeigniter where? I want to convert following query in to codeigniter form
My query
SELECT rq_id, rq_plant_4sale_code, rq_serial_number, rq_quantity_requested, rq_requester_farm_id,
rq_fulfiller_farm_id, rqpri_description, rqrem_remark,rqrem_remark_datetime, rq_created_datetime,
plsal_name_botanical, plsal_name_english, pot_code, rqpri_description
FROM (reqn_requisitions)
LEFT JOIN reqn_requisition_priorities ON(rq_priority_rank=rqpri_rank)
LEFT JOIN reqn_requisition_remarks ON(rq_id=rqrem_reqn_id)
LEFT JOIN tukai_plants_4sale ON(rq_plant_4sale_code=plsal_id)
LEFT JOIN tukai_pots ON(plsal_pot_id=pot_id)
WHERE rqrem_remark_datetime IN(SELECT MAX(rqrem_remark_datetime) AS dt FROM reqn_requisition_remarks GROUP BY rqrem_reqn_id ) AND rq_challan_id=0'
I am trying like this
$this->db->select("rq_id, rq_plant_4sale_code, rq_serial_number, rq_quantity_requested, rq_requester_farm_id,
rq_fulfiller_farm_id, rqpri_description, rqrem_remark,rqrem_remark_datetime, rq_created_datetime,
plsal_name_botanical, plsal_name_english, pot_code, rqpri_description ");
$this->db->join('tukai_plants_4sale',
'tukai_plants_4sale.plsal_id = reqn_requisitions.rq_plant_4sale_code','left');
$this->db->join('tukai_pots',
'tukai_pots.pot_id = tukai_plants_4sale.plsal_pot_id','left');
$this->db->join('reqn_requisition_remarks',
'reqn_requisition_remarks.rqrem_reqn_id = reqn_requisitions.rq_id','left');
$this->db->order_by("rq_id","desc");
For complex where clause conditions you can use,
$this->db->where('<where condition here>', NULL, FALSE);
From docs:
$this->db->where() accepts an optional third parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks.
Try below code:
/* Replace table_name with appropriate table names */
$this->db->select("table_name.rq_id, table_name.rq_plant_4sale_code, table_name.rq_serial_number, table_name.rq_quantity_requested, table_name.rq_requester_farm_id,
table_name.rq_fulfiller_farm_id, table_name.rqpri_description, rqrem_remark,table_name.rqrem_remark_datetime, table_name.rq_created_datetime,
table_name.plsal_name_botanical, table_name.plsal_name_english, table_name.pot_code, table_name.rqpri_description ");
$this->db->from('reqn_requisitions');
$this->db->join('reqn_requisition_priorities','reqn_requisitions.rq_priority_rank = reqn_requisition_priorities.rqpri_rank','left');
$this->db->join('reqn_requisition_remarks','reqn_requisition_remarks.rqrem_reqn_id = reqn_requisitions.rq_id','left');
$this->db->join('tukai_plants_4sale','tukai_plants_4sale.plsal_id = reqn_requisitions.rq_plant_4sale_code','left');
$this->db->join('tukai_pots','tukai_pots.pot_id = tukai_plants_4sale.plsal_pot_id','left');
$this->db->where('reqn_requisition_remarks.rqrem_remark_datetime IN(SELECT MAX(rqrem_remark_datetime) AS dt FROM reqn_requisition_remarks GROUP BY rqrem_reqn_id', NULL, FALSE);
$this->db->where('table_name.rq_challan_id', 0);
$this->db->order_by("table_name.rq_id","desc");
$query = $this->db->get();
return $query->result();
An alternative:
If your query (anyhow) cannot be written using CI's Active Record, you can always use a simple method:
$this->db->query('<your SQL query here>');
For example:
$query = $this->db->query('SELECT rq_id, rq_plant_4sale_code, rq_serial_number,rq_quantity_requested, rq_requester_farm_id,rq_fulfiller_farm_id, rqpri_description,rqrem_remark,rqrem_remark_datetime, rq_created_datetime,
plsal_name_botanical, plsal_name_english, pot_code, rqpri_description
FROM (reqn_requisitions)
LEFT JOIN reqn_requisition_priorities ON(rq_priority_rank=rqpri_rank)
LEFT JOIN reqn_requisition_remarks ON(rq_id=rqrem_reqn_id)
LEFT JOIN tukai_plants_4sale ON(rq_plant_4sale_code=plsal_id)
LEFT JOIN tukai_pots ON(plsal_pot_id=pot_id)
WHERE rqrem_remark_datetime IN(SELECT MAX(rqrem_remark_datetime) AS dt FROM reqn_requisition_remarks GROUP BY rqrem_reqn_id ) AND rq_challan_id=0');
return $query->result();

mysql select from a view with where condition gives different result than executing the view definition with where condition

I have a view with the following definition:
select
`cb_trans_detail`.`numero_partida` AS `numero_partida`,
`cb_trans_head`.`fecha_partida` AS `fecha_partida`,
`cb_trans_detail`.`concepto_partida` AS `concepto_partida`,
`cb_cuenta`.`nombre_cuenta` AS `nombre_cuenta`,
`cb_cuenta`.`codigo_mayor` AS `codigo_mayor`,
`cb_mayor`.`nombre_mayor` AS `nombre_mayor`,
`cb_mayor`.`categoria` AS `categoria`,
`cb_categoria`.`nombre` AS `nombre`,
`cb_categoria`.`presentacion` AS `presentacion`,
`cb_trans_detail`.`codigo_cuenta` AS `codigo_cuenta`,
sum(`cb_trans_detail`.`debito_partida`) AS `Debitos`,
sum(`cb_trans_detail`.`credito_partida`) AS `Creditos`,
`cb_cuenta`.`saldo_inicial` AS `saldo_inicial`,
((`cb_cuenta`.`saldo_inicial` +
sum(`cb_trans_detail`.`debito_partida`)) -
sum(`cb_trans_detail`.`credito_partida`)) AS `Saldo`,
concat(`cb_mayor`.`categoria`,`cb_cuenta`.`codigo_mayor`,`cb_trans_detail`.`codigo_cuenta`)
AS `Codigo`
from
((((`cb_trans_detail` join `cb_cuenta`
on(((`cb_trans_detail`.`codigo_cuenta` = `cb_cuenta`.`codigo_cuenta`)
and (`cb_trans_detail`.`categoria` = `cb_cuenta`.`categoria`)
and (`cb_trans_detail`.`codigo_mayor` = `cb_cuenta`.`codigo_mayor`))))
join `cb_mayor` on(((`cb_cuenta`.`codigo_mayor` = `cb_mayor`.`codigo_mayor`)
and (`cb_cuenta`.`categoria` = `cb_mayor`.`categoria`))))
join `cb_categoria` on(((`cb_mayor`.`categoria` = `cb_categoria`.`categoria`)
and (`cb_trans_detail`.`categoria` = `cb_categoria`.`categoria`))))
left join `cb_trans_head` on((`cb_trans_detail`.`numero_partida` =
`cb_trans_head`.`numero_partida`)))
where
(`cb_categoria`.`presentacion` = '1')
group by concat(`cb_mayor`.`categoria`,`cb_cuenta`.`codigo_mayor`,
`cb_trans_detail`.`codigo_cuenta`)
If I select from this view as follows:
SELECT
`balance_general_view`.`numero_partida`,
`balance_general_view`.`fecha_partida`,
`balance_general_view`.`concepto_partida`,
`balance_general_view`.`nombre_cuenta`,
`balance_general_view`.`codigo_mayor`,
`balance_general_view`.`nombre_mayor`,
`balance_general_view`.`categoria`,
`balance_general_view`.`nombre`,
`balance_general_view`.`presentacion`,
`balance_general_view`.`codigo_cuenta`,
`balance_general_view`.`Debitos`,
`balance_general_view`.`Creditos`,
`balance_general_view`.`saldo_inicial`,
`balance_general_view`.`Saldo`,
`balance_general_view`.`Codigo`
FROM
`balance_general_view`
WHERE
`balance_general_view`.`fecha_partida` BETWEEN '2014-01-01' AND '2014-01-31'
this yields a different result than if I execute the query as follows:
select
`cb_trans_detail`.`numero_partida` AS `numero_partida`,
`cb_trans_head`.`fecha_partida` AS `fecha_partida`,
`cb_trans_detail`.`concepto_partida` AS `concepto_partida`,
`cb_cuenta`.`nombre_cuenta` AS `nombre_cuenta`,
`cb_cuenta`.`codigo_mayor` AS `codigo_mayor`,
`cb_mayor`.`nombre_mayor` AS `nombre_mayor`,
`cb_mayor`.`categoria` AS `categoria`,
`cb_categoria`.`nombre` AS `nombre`,
`cb_categoria`.`presentacion` AS `presentacion`,
`cb_trans_detail`.`codigo_cuenta` AS `codigo_cuenta`,
sum(`cb_trans_detail`.`debito_partida`) AS `Debitos`,
sum(`cb_trans_detail`.`credito_partida`) AS `Creditos`,
`cb_cuenta`.`saldo_inicial` AS `saldo_inicial`,
((`cb_cuenta`.`saldo_inicial` + sum(`cb_trans_detail`.`debito_partida`)) - sum(`cb_trans_detail`.`credito_partida`)) AS `Saldo`,
concat(`cb_mayor`.`categoria`,`cb_cuenta`.`codigo_mayor`,`cb_trans_detail`.`codigo_cuenta`) AS `Codigo`
from
((((`cb_trans_detail` join `cb_cuenta` on(((`cb_trans_detail`.`codigo_cuenta` = `cb_cuenta`.`codigo_cuenta`) and (`cb_trans_detail`.`categoria` = `cb_cuenta`.`categoria`) and (`cb_trans_detail`.`codigo_mayor` = `cb_cuenta`.`codigo_mayor`)))) join `cb_mayor` on(((`cb_cuenta`.`codigo_mayor` = `cb_mayor`.`codigo_mayor`) and (`cb_cuenta`.`categoria` = `cb_mayor`.`categoria`)))) join `cb_categoria` on(((`cb_mayor`.`categoria` = `cb_categoria`.`categoria`) and (`cb_trans_detail`.`categoria` = `cb_categoria`.`categoria`)))) left join `cb_trans_head` on((`cb_trans_detail`.`numero_partida` = `cb_trans_head`.`numero_partida`)))
where
(`cb_categoria`.`presentacion` = '1') and `cb_trans_head`.`fecha_partida` BETWEEN '2014-01-01' and '2014-01-31'
group by
concat(`cb_mayor`.`categoria`,`cb_cuenta`.`codigo_mayor`,`cb_trans_detail`.`codigo_cuenta`)
My question is: How to get the result I need using the view and filtering programatically instead of hard-coding the where condition? Thank you. If you need the individual table definitions let me know. Much appreciated.
If you use a left join to a table X and a condition in the WHERE-clause to this table X, you change your left join to an inner one. If you want to restrict the results by the values of this left joined table, you must use this condition in the ON clause of the left join instead:
...
LEFT JOIN
cb_trans_head
ON
cb_trans_detail.numero_partida = cb_trans_head.numero_partida
AND
cb_trans_head.fecha_partida BETWEEN '2014-01-01' and '2014-01-31'
...
If there's another one that I overlook, tread it the same way.

How to search exact string using MySql Query which avoids extended values?

My Query looks like
$search_query = db_query("SELECT nd.nid, users.name, nd.type FROM node as nd
LEFT JOIN node_revisions as nd_rev ON nd_rev.nid = nd.nid AND nd_rev.vid = nd.vid
LEFT JOIN users ON nd.uid = users.uid
WHERE nd.status = 1 AND nd_rev.body LIKE LOWER('%node/100%')
AND nd.nid NOT IN(SELECT DISTINCT nid FROM term_node WHERE tid = 293)");
This query actually returns all the matches from node_revisions.body field, Which includes
node/1000, node/1001.... Etc.,
I want to get only the result of exact match where possible like
"node/100"
"node/100/"
"/node/100"
"/node/100/"
'node/100'
'node/100/'
'/node/100'
'/node/100/'
and not like
"node/1006"
"node/10064/"
"/node/1000"
"/node/10001/"
'node/10023'
'node/1005/'
'/node/1001'
'/node/10069/'
This above query returned me result which has string like below..
..a href="/node/1006"
How to avoid this kind of errors? Please help..
Try removing the % after 100 so the search won't consider any digit after 100, like this:
LOWER('%node/100')
Then consider the following Regular Expression
Example:
`nd_rev.body` REGEXP "^/?node/100/?$"
Oh ya... I got an resolution for this.. I redefined my query like below and it gives me result as expected..
$search_query = db_query("SELECT nd.nid, users.name, nd.type FROM node as nd
LEFT JOIN node_revisions as nd_rev ON nd_rev.nid = nd.nid AND nd_rev.vid = nd.vid
LEFT JOIN users ON nd.uid = users.uid
WHERE nd.status = 1 AND nd_rev.body RLIKE '[[:<:]]" . $search_string . "[[:>:]]'
AND nd.nid NOT IN(SELECT DISTINCT nid FROM term_node WHERE tid = 293)");
Look at
nd_rev.body RLIKE '[[:<:]]" . $search_string . "[[:>:]]'
This is what i expected