I want to count for each of the values in the select. I need to know how many values there are in each a.merk, b.brandstof, a.bouwjaar, k.kleur, t.transmissie. So I need 5 different values. How can I do this?
public function searchFilter() {
$query = (new Query())
->select([
'GROUP_CONCAT(DISTINCT(a.merk), ".", m.merk ORDER BY a.merk ASC) merk',
'GROUP_CONCAT(DISTINCT(b.brandstof) ORDER BY b.brandstof ASC) brandstof',
'GROUP_CONCAT(DISTINCT(a.bouwjaar) ORDER BY a.bouwjaar DESC) bouwjaar',
'GROUP_CONCAT(DISTINCT(k.kleur) ORDER BY k.kleur ASC) kleur',
'GROUP_CONCAT(DISTINCT(t.transmissie) ORDER BY t.transmissie ASC) transmissie',
])
->from('auto_new a')
->join('INNER JOIN', 'tbl_merken m', 'a.merk = m.merk_id') //Merk
->join('INNER JOIN', 'tbl_kleur k', 'a.kleur = k.kleur_id') //Kleur
->join('INNER JOIN', 'tbl_transmissie t', 'a.transmissie = t.transmissie_id') //Transmissie
->join('INNER JOIN', 'tbl_brandstof b', 'a.brandstof = b.brandstof_id'); //Brandstof
return $query;
}
this is the output I get.
In this function I execute the query.
public function actionSearchfilter($ac) {
Yii::$app->response->format = Response::FORMAT_JSON;
$query = Car::searchFilter()->where(['a.ac' => $ac, 'a.flag' => '1'])->all();
return $query;
}
I only need to count the DISTINCT values.
Related
How do I optimize these queries to be one or two? The one in the loop to be one at least.
$applicantIds = \DB::select()->from( 'applicants' )->where( 'created_at', 0 )->execute();
foreach ($applicantIds as $applicantId)
{
$applicantApp = \DB::select( 'applicant_id', 'created_at' )->from( 'applicant_apps' )->where( 'applicant_id', $applicantId['id'] )->execute();
\DB::update( 'applicants' )->value( 'created_at', $applicantApp[0]['created_at'] )->where( 'id', $applicantApp[0]['applicant_id'] )->execute();
}
Try this:
$applicantIds = \DB::select()->from( 'applicants' )->where( 'created_at', 0 )->execute();
$applicantApps = \DB::select( 'applicant_id', 'created_at' )->from( 'applicant_apps' )->where( 'applicant_id', 'in', $applicantIds)->execute();
$statement = '';
foreach ($applicantApps as $applicantApp)
{
$applicantId = $applicantApp['applicant_id'];
$applicantCreatedAt = $applicantApp['created_at'];
$statement .= "update applicants set created_at='$applicantCreatedAt' where id = '$applicantId';"
}
if ($statement) {
\DB::query($statement)->execute();
}
Two queries only will get you this.
And you can add some logic in foreach block if you need.
I I understand you, you can use singe query for this:
update applicants a
join applicant_apps aa on aa.applicant_id = a.id
set a.created_at = aa.created_at
where a.created_at = 0;
When you want to use Laravel syntax:
$db::table('applicants as a')
->where( $db::raw("`a`.`created_at`"), 0)
->join('applicant_apps as aa', 'aa.applicant_id', '=', 'a.id')
->update([ 'a.created_at' => $db::raw("`aa`.`created_at`") ])
;
Online test
#faesal with your answer I changed it to have some arrays as ID's
$applicantIds = \DB::select('id')->from( 'applicants' )->where( 'created_at', 0 )->execute()->as_array('id');
$applicantApps = \DB::select( 'applicant_id', 'created_at' )->from( 'applicant_apps' )->where( 'applicant_id', 'in', array_keys($applicantIds))->execute();
$statement = '';
foreach ($applicantApps as $applicantApp)
{
$applicantId = $applicantApp['applicant_id'];
$applicantCreatedAt = $applicantApp['created_at'];
$statement .= "update applicants set created_at='$applicantCreatedAt' where id = '$applicantId';";
}
\DB::query($statement)->execute();
How can I convert this raw query into query builder yii2 as I am getting the record using sub-query:
RAW QUERY:
SELECT *
FROM (
SELECT DISTINCT `comp`.*,TIMESTAMPDIFF(HOUR,comp.created_date,comp.updated_date)
AS hours
FROM `complaints` `comp`
INNER JOIN `complaint_log` `comp_log` ON comp_log.`comp_id` = comp.`id`
WHERE ((comp.name LIKE '%%' OR comp.id LIKE '%%' OR comp.phone_no LIKE '%%')
AND DATE(comp.created_date)
BETWEEN '2018-01-01' AND '2020-03-20')
AND (comp.is_delete = 0)
ORDER BY `comp`.`id` DESC, `comp`.`created_date` DESC)
AS cte_name WHERE hours > 120;
Yii2 Query
$query = (new \yii\db\Query())
->select('comp.*')
->from('complaints comp
->distinct()
->innerJoin('complaint_log as comp_log', 'comp_log.`comp_id` =comp.`id`')
->where($search)
->andWhere('comp.is_delete = 0')
->orderBy("comp.id DESC")
->addOrderBy('comp.created_date DESC');
Try following code:
$subquery = (new \yii\db\Query())
->select(['comp.*', 'TIMESTAMPDIFF(HOUR, comp.created_date, comp.updated_date) AS hours'])
->distinct()
->from('complaints comp')
->innerJoin('complaint_log comp_log', 'comp_log.comp_id = comp.id')
->where(['or',
['like', 'comp.name', $search_name],
['or',
['like', 'comp.id', $search_id],
['like', 'comp.phone_no', $search_phone],
]
])
->andWhere('DATE(comp.created_date) BETWEEN :cStart AND :cEnd', [':cStart' => '2018-01-01', ':cEnd' => '2020-03-20'])
->andWhere(['comp.is_delete' => 0])
->orderBy(['comp.id' => SORT_DESC, 'comp.created_date' => SORT_DESC])
;
$query = (new \yii\db\Query())
->select('cte_name.*')
->from(['cte_name' => $subquery])
->where(['>', 'cte_name.hours', 120])
;
You can use createCommand() function: use below query.
$connection = \Yii::$app->db;
$query = $connection->createCommand(
'
SELECT * FROM (
SELECT DISTINCT comp.*,TIMESTAMPDIFF(HOUR,comp.created_date,comp.updated_date) AS hours
FROM complaints comp
INNER JOIN complaint_log comp_log ON comp_log.comp_id = comp.id
WHERE ('.$search.')
AND (comp.is_delete = 0)
ORDER BY comp.id DESC, comp.created_date DESC
) AS cte_name WHERE hours > 120;
');
$data = $query->queryAll();
Put your raw query in createCommand() function. Here i used $search variable as you used in your sub query
Is there a way to select NULL value or an exact string in a query in YII2?
I am trying to join 3 queries and I need the same number of columns queries and something like "select NULL as returned, submitted, amount, NULL as iamount....."
Example:
$subQuery2 = Loan::find()->select('person_id')->where(['sheet_id' => $id]);
$query2 = new Query();$query2 = new Query();
$query2->select(['last_name','first_name','fc.tax','NULL as returned','fc.submitted','fc.amount','NULL as iamount','NULL as interest',
'b.month','b.year','b.nb'])
->from('sheet as b')
->join('JOIN', 'fee as fc',
'b.id = fc.sheet_id')
->join('JOIN','person','fc.person_id = person.id')
->where(['b.id' => $id])
->andWhere(['not in', 'person_id', $subQuery2]);
$query = new Query();
$query->
select(['last_name','first_name','fc.tax','fi.returned','fc.submitted','fc.amount','fi.amount as iamount','fi.interest',
'b.month','b.year','b.nb'])
->from('sheet as b')
->join('RIGHT JOIN', 'fee as fc',
'b.id = fc.sheet_id')
->join('JOIN','person','fc.person_id = person.id')
->join('LEFT JOIN','loan as fi',
'b.id = fi.sheet_id and fc.person_id = fi.person_id')
->where(['b.id' => $id])
->union($query2)
->orderBy(['last_name' => SORT_DESC]);
Yes, you have two ways to do it:
$query = new Query();
$query->select([
new Expression('NULL as test')
'test2' => new Expression('NULL'),
])->from('sheet as b');
Both of selects will do the same, but the second line (test2) is preferable as it is more DBMS-agnostic.
I'm new in Yii2, and I have a query with right result:
SELECT DISTINCT workloadTeam.project_id, wp.project_name, workloadTeam.user_id, workloadTeam.commit_time, wp.workload_type FROM
(SELECT p.id, p.project_name, w.user_id, w.commit_time, w.comment, w.workload_type
FROM workload as w, project as p
WHERE w.user_id = 23 AND p.id = w.project_id) wp
INNER JOIN workload as workloadTeam ON wp.id = workloadTeam.project_id
But in my ModelSearch.php, I wrote:
$user_id = Yii::$app->user->id;
$subquery = Workload::find()->select('p.id', 'p.project_name', 'w.user_id', 'w.commit_time', 'w.comment', 'w.workload_type')
->from(['project as p', 'workload as w'])
->where(['user_id' => $user_id, 'p.id' => 'w.project_id']);
$query = Workload::find()
->select(['workloadTeam.project_id', 'wp.project_name', 'workloadTeam.user_id', 'workloadTeam.from_date', 'workloadTeam.to_date', 'workloadTeam.workload_type', 'workloadTeam.comment'])
->where(['', '', $subquery]);
$query->join('INNER JOIN', 'workload as workloadTeam', 'wp.id = workloadTeam.project_id');
It happended error:
SELECT COUNT(*) FROM `workload` INNER JOIN `workload` `workloadTeam` ON wp.id = workloadTeam.project_id WHERE `` (SELECT p.project_name `p`.`id` FROM `project` `p`, `workload` `w` WHERE (`user_id`=20) AND (`p`.`id`='w.project_id'))
And I can't fix it with right query above.
You have any solution about this?
Is this error shown in the Yii-debug toolbar? Then your query (which you mentioned as error) is probably only the count from the query which is listed before.
You missed to add the sub-query in from clause like you shown in your working sql. Add this in your where clause were just the wrong place. Put sub-queries in whereconditions, if you have scalar results, because you have to use this result with operands like =, >=, in...
This could work:
$user_id = Yii::$app->user->id;
$subquery = Workload::find()->select([
'p.id as id',
'p.project_name as project_name',
'w.user_id as user_id',
'w.commit_time as commit_time',
'w.comment as comment',
'w.workload_type as workload_type'
])
->from([
'project as p',
'workload as w'
])
->where([
'user_id' => $user_id,
'p.id' => 'w.project_id'
]);
$query = Workload::find()
->select([
'workloadTeam.project_id',
'wp.project_name',
'workloadTeam.user_id',
'workloadTeam.from_date',
'workloadTeam.to_date',
'workloadTeam.workload_type',
'workloadTeam.comment'
])
->from([$subquery => 'wp']); //you were missing this line
$query->join('INNER JOIN', 'workload as workloadTeam', 'wp.id = workloadTeam.project_id');
But you don't use any selects from your workload table in your main-query $query...
Since I don't know what's your goal to achieve I can't help you at this topic...
I am facing a problem when using active record or_where
how i do or only for one particular field i.e meeting_status
$this->db->_protect_identifiers=false;
$this->db->select("g.category_id,f.doc_type_id,g.category_name,f.doc_type_name,c.meeting_name_id, c.meeting_name as mn, d.meeting_type_id, d.meeting_type_name, e.venue_id, e.venue_name, u.*, (select count(*) from tbl_meeting_decisions where meeting_id=u.meeting_id and record_status= 'ACTIVE') as `meeting_decision`, (select count(*) from tbl_meeting_actions where meeting_id=u.meeting_id and record_status= 'ACTIVE') as `meeting_action`, (select count(*) from tbl_meeting_actions where meeting_id=u.meeting_id and action_status='OPEN' and record_status= 'ACTIVE') as `meeting_close_action`");
$this->db->from('tbl_meeting_plans u');
$this->db->join('tbl_meeting_names c', 'c.meeting_name_id = u.meeting_name');
$this->db->join('tbl_meeting_types d', 'd.meeting_type_id = u.meeting_mode_id');
$this->db->join('tbl_meeting_venue e', 'e.venue_id = u.venue_id ');
$this->db->join('tbl_document_types f', 'f.doc_type_id = u.meeting_type_id ');
$this->db->join('tbl_categories g', 'g.category_id = u.meeting_category_id ');
$this->db->where(array('u.meeting_type_id'=>$str2,'u.meeting_category_id'=>$str1,'u.meeting_status'=>'Planning','u.record_status'=>'ACTIVE' ));
$this->db->or_where(array('u.meesting_status'=>'Meeting Updated' ));
$where = "(u.meeting_status='Planning' or u.meeting_status='Meeting
Updated') ";
$this->db->where($where);
Before this use the normal where clause