Hi i have following query where it's use joininner statement to get all possible businesses. But when a business is created for first time only 1 category will be updated the rest 2 will remain null
public function searchBusinessByCategoryString($str = null, $city=null,$start,$perpage)
{
$select = $this->getDbTable()->getAdapter()->select();
$select->from('business as b', array('b.business_name','b.business_url','b.reviews_num','b.cat_id','b.business_id','b.rating','b.business_phone','b.business_add1','b.business_add2','b.x','b.y','b.photo_url'))
->joinInner('business_category as bc','b.cat_id = bc.cat_id',array('bc.cat_name'))
->joinInner('business_sub_category as bsc','b.sub_cat_id = bsc.b_sub_cat_id',array('bsc.b_subcat_name','bsc.b_sub_cat_id'))
->joinInner('business_sub_category as bsc2','b.sub_cat2_id = bsc2.b_sub_cat_id',array('bsc2.b_subcat_name','bsc2.b_sub_cat_id'))
->joinInner('business_sub_category as bsc3','b.sub_cat3_id = bsc3.b_sub_cat_id',array('bsc3.b_subcat_name','bsc3.b_sub_cat_id'))
->where("bsc.b_subcat_name like '".$str."%'")
->orWhere("bsc.b_subcat_name like '%".$str."'")
->orWhere("bsc.b_subcat_name= '".$str."'")
->orWhere("bsc2.b_subcat_name like '%".$str."'")
->orWhere("bsc2.b_subcat_name = '".$str."'")
->orWhere("bsc2.b_subcat_name like '".$str."%'")
->orWhere("bsc3.b_subcat_name like '%".$str."'")
->orWhere("bsc3.b_subcat_name = '".$str."'")
->orWhere("bsc3.b_subcat_name like '".$str."%'");
$result = $this->getDbTable()->getAdapter()->fetchAll($select);
return $result;
}
Now the issues is how can i not doing joininner query if the rest 2 categories are null? My above statement return empty result event though there is businesses with one category.
use leftJoin instead of innerJoin where the joined table can contain NULL value. INNER JOIN will join table, using the condition and will not keep lines when a null value is found on the joined table. LEFT JOIN will allow you to keep this line
Related
"Table1":
id
name
1
Ulrich
2
Stern
"Table2":
id
school
tid
1
A
1
2
B
1
I want to join 2 table to get all information. With SQL query like this:
SELECT Table1.id,
name,
school
FROM `Table1`
INNER JOIN `Table2`
ON Table1.id = Table2.tid
It gives me all information as I expect (I mean 2 rows with name 'Ulrich').
But when I do with Yii2 query:
$query = self::find();
$query -> alias('t1')
-> innerJoin(['t2'=>'Table2'], 't1.id=t2.tid')
$result = NULL;
if($total = $query->count()) {
$result = $query
-> select([t1.*, t2.school])
->asArray()
->all()
;
$result[0]['count'] = $total;
}
it only gives me 1 row with name 'Ulirch'.
Can anyone help me with this problem. Thank you very much.
If you use ActiveRecord::find() method to create query you will get instance of yii\db\ActiveQuery. This is query designed to load ActiveRecord models. Because of that if you do any type of join and your result set contains primary key of your main model (The model which find() method was called to create query) the ActiveQuery will remove any rows it considers duplicate.
The duplicates are recognised based on main model primary key so the rows in resultset will be considered duplicate even if the data from joined table are different. That's exactly what happened in your case.
To avoid that you have to use query builder instead of ActiveQuery.
Your query can look for example like this:
$query = (new \yii\db\Query())
->from(['t1' => self::tableName()])
->innerJoin(['t2'=>'Table2'], 't1.id=t2.tid');
Setup:
Codeigniter 3 running on a variant of PHP 5 server. Using the Query Builder to deal with the db.
Background:
Creating a software that has a client profile. Users can add multiple notes to the profile, and link a contact to that note. The profile then displays all the notes and the contact on the corresponding profile, using the join() method from Codeigniter 3's Query Builder.
Issue:
A note can be added without a client contact, in the case of a generalised note. This sets the default value of NULL in the DB which in turn prevents the client_model from returning the notes, because it cant join the tables.
Current code:
function get_client_notes($client_id)
{
$this->db->join('nh_note_types', 'nh_note_types.type_id = nh_client_notes.client_notes_type');
$this->db->join('nh_user_profiles', 'nh_user_profiles.user_profile_user_id = nh_client_notes.client_notes_added_by');
$this->db->join('nh_client_contacts', 'nh_client_contacts.client_contact_id = nh_client_notes.client_notes_client_contact_id');
$this->db->order_by("client_notes_added_date", "desc");
$query = $this->db->get_where('nh_client_notes', array('client_notes_client_id' => $client_id));
return $query;
}
Currently if the value for client_notes_client_contact_id is NULL it will not return any data for that row.
What I am trying to find out is if there is a way to do the following:
IF the client_notes_client_contact_id is not null then join the tables, else carry on past.
Or any other way that would join the tables if there is a value and where it is NULL, then don't join.
Any help is appreciated!
Your current MySQL query with the above Query builder would 'build' like this:
SELECT
*
FROM
nh_client_notes
JOIN nh_note_types ON
( nh_note_types.type_id = nh_client_notes.client_notes_type )
JOIN nh_user_profiles ON
( nh_user_profiles.user_profile_user_id = nh_client_notes.client_notes_added_by )
JOIN nh_client_contacts ON
( nh_client_contacts.client_contact_id
=
nh_client_notes.client_notes_client_contact_id
)
WHERE
client_notes_client_id = 479
ORDER BY
client_notes_added_date DESC
However, this will require all the JOINs to have an matching ID Available. Thus the correct MySQL would be LEFT JOIN on client_notes_client_contact_id key, which is as you've requested to be conditional.
In this instance, adjust your Query builder to have a third parameter on the join() to make this 'left'.
<?php
$this->db->join(
'nh_client_contacts',
'nh_client_contacts.client_contact_id = nh_client_notes.client_notes_client_contact_id',
'left'
);
?>
In doing so, this'll correct your query to bring back client_notes regardless of client_notes_client_contact_id.
My Problem: Getting query results from 2 db tables with PROPEL2 even when second table has no corresponding entries. If the second has corresponding entries than it is no problem.
I have 3 tables: Entry, Contingent and Favorit.
The schema is as follow:
Entry.id [PK]
Entry.contingent_id [FK]
Entry.expert_id
Contingent.id [PK]
Contingent.name
Favorit.id [PK]
Favorit.contingent_id [FK]
Favorit.expert_id
Favorit.pos
I want to get for a specified expert_id ($id) all entries from Entry with contingent-name and if exists the favorit.pos for this expert and contingent. I get the wanted with:
$result = EntryQuery::create()
->filterByExpertId($id)
->join('Entry.Contingent')
->withColumn('Contingent.name','_contingentName')
->join('Contingent.Favorit')
->where('Favorit.expert_id = ?', $id)
->find();
This works only if there exists such a favorit.pos . In some cases this element doesn’t exists (what is wanted from the system). In these cases I want to get the result too just with favorit.pos as empty, null or 0. But Propel doesn’t return me these records.
With MySQL I have no problem to get the desired result:
SELECT entry.* ,
(SELECT favorit.position
FROM contingent, favorit
WHERE
favorit.expert_id = entry.expert_id
AND entry.contingent_id = contingent.id
AND contingent.id = favorit.contingent_id
)
FROM `entry`
JOIN contingent
ON entry.contingent_id = contingent.id
WHERE
entry.expert_id=1;
Use Join left in code:
->join('Contingent.Favorit','selection conditon','left' )
This left work when empty database when condition is false
in condition like 'id'=$id
I have a nested relationship and I would like to filter them, using the result that comes from the first query run by Eloquent.
My Eloquent query is:
$entry = Entry::with([
'products.unit',
'products.area'
])->find($id);
The query log shows me that Eloquent runs this query first:
select * from entry where entry.deleted_at is null and entry.id = ? limit 1
And I would like to use its result in this second query, also run by Eloquent:
select area.*,
area_product.product_id, area_product.quota as pivot_quota,
area_product.month as pivot_month
from area inner join area_product
on area.id = area_product.area_id
where area.deleted_at is null and area_product.product_id in (?)
I would like to put a constraint inside it using the month value that comes from the first query.
Is there a way to do it using Eloquent?
I was thinking in something like this:
$entry = Entry::with([
'products.unit',
'products.area' => function ($q) {
// using month here!
}
])->find($id);
I have two tables 'accounts_transactions' and 'accounts_bills_transactions'.
I have to left join these two using active record of codeigniter.But the names of key columns used to join are different.So I am not getting the key column from the left table in the output .What query should I write to get the key column from the left table included in the result.
My code is
$this->db->select('*');
$this->db->from('accounts_transactions');
$this->db->join('accounts_bills_transactions', 'accounts_transactions.id = accounts_bills_transactions.transaction_id','left');
$query = $this->db->get();
So, as you see the key columns used to join here are , id from left table and transaction_id from second table.The problem is that I am not getting the id from left table in the result.But I am getting all other columns.I assume the problem is because of difference in column names used to join.ie both the column names are not named 'id' .So how can I get the id from left table included in the result.
You could alias them:
$this->db->select('accounts_transatctions.*, account_transactions.id AS a_id,
accounts_bills_transactions.*,
account_bills_transactions.id AS ab_id');
$this->db->from('accounts_transactions');
$this->db->join('accounts_bills_transactions', 'accounts_transactions.id = accounts_transactions.transaction_id','left');
$query = $this->db->get();
The two IDs will now be available as a_id and ab_id (or whatever alias you choose)
Note: I'm not sure if you can alias in AR without avoiding escaping (haven't been using CI for a while). Should you get any error for that reason, just pass false as second parameter of $this->db->select():
$this->db->select('...', false);
you can try this if you confuse of using $this->where or $this->join
$query = $this->db->query("select ......");
return $query;
You problem is so simple. You can use this query
$query = $this->db
->select('at.*')
->select('abt.id as abt_id');
->from('accounts_transactions at');
->join('accounts_bills_transactions abt', 'at.id = abt.transaction_id','left');
->get()
->result();
When same column are used in join it selects only one. You need to give alise to the other column in second table. The best practice is to use a structure like this
accounts_transatctions
--------------------------
accounts_transatctions_id
other_columns
accounts_bills_transactions
---------------------------
accounts_bills_transactions_id
accounts_transatctions_id
other_columns