How to convert mysql query to codeigniter using query builder? - php

The following is my mysql query:
select * from db_posts LEFT JOIN db_followers ON db_posts_user_id = db_followers_following AND db_followers_user_id = 276
How can I convert it to codeigniter using query builder?
$this->db->where('db_posts_user_id', 'db_followers_following');
$this->db->where('db_followers_user_id', 276);
$this->db->order_by('db_posts.db_posts_id', 'DESC');
$this->db->join('db_followers', 'db_followers.db_followers_following = db_posts.db_posts_user_id');
$query2 = $this->db->get('db_posts')->result_array();
I get the required result when I use mysql query. But I get a blank array when I use codeigniter queries. What is wrong in my CI Query?

why are you using those where clause? if you are using it as condition for your 'JOIN' process, try it like this:
$this->db->order_by('db_posts.db_posts_id', 'DESC');
$this->db->join('db_followers', 'db_followers.db_followers_following = db_posts.db_posts_user_id and db_followers_user_id = 276', 'left');
$query2 = $this->db->get('db_posts')->result_array();
Points to Note
1)as previous comments said, you should 'Left Join' if you want to get all posts from 'db_posts'.
2) You can add Multiple conditions in ON Clause using and but within ''. all your conditions should be specified before second comma(,) which is before mentioning 'LEFT'.
Hope this will help. Lemme know if this help

Try adding the "Left" option to tell it what kind of join to do:
$this->db->join('db_followers', 'db_followers.db_followers_following = db_posts.db_posts_user_id', 'Left');
Also I'm not sure you need
$this->db->where('db_posts_user_id', 'db_followers_following');
this is already covered by your JOIN statement.
Source:
http://www.bsourcecode.com/codeigniter/codeigniter-join-query/#left-join and https://www.codeigniter.com/userguide3/database/query_builder.html

Related

Cross Join with php codeigniter query

Is there away to cross join from php. In example:
Currently I query a database like so:
$company_id = 20;
$templates_data = $this->db->select('template_id')
->from('dr_template_relational')
->where('dr_template_relational.company_id',$company_id)
->get()
->result_array();
What I'm looking to do is something like this:
->from('dr_template_relational')
->cross_join()
There's several responses to this question on SO but post reference a regular sql query like so:
"SELECT * FROM citys LEFT JOIN comments ON comments.city=citys.city WHERE citys.id=$id";
This would be the way to do it in SQL query but the point here is to do it in php and get the data returned with a cross join. I also realize the query can be made with in php to have it select the data and join it with code but my question is related to is there away to simply add ->cross_join() or something like that.
You can run raw query in codeigniter to solve your problem as below:
$sql 'your query here with cross join';
$query = $this->db->query($sql);
return $query->result_array();
Hope it helps you :)
You can use CI join method.
$company_id = 20;
$templates_data = $this->db->select('dr_template_relational.template_id')
->where('dr_template_relational.company_id',$company_id)
->join('table','dr_template_relational.company_id=table.company_id','LEFT')
->get()
->result_array();
where 'LEFT' is the join type

Laravel query with temporary table

How to convert this query to laravel db query.
SELECT * FROM {
Select * from organizers
Order by organizers.rank
} Group by t.department
This is simplified version of query. In real the inner query has more where clause and built using laravel db query.
Edit: I am aware of raw query. But that's not what I am looking for. Inner query is complex and has lots of conditional where clause. I would like to retain the db query object I used there.
You can have 2 different query builders and merge their binding like below :
$innerQuery = DB::table('organizers')->orderBy('organizers.rank');
$mainQuery = DB::table(DB::raw('(' . $innerQuery->toSql() . ') as t'))
->mergeBindings($innerQuery->getQuery())
->groupBy('t.department')
->get();
This will also help you retail the $innerQuery builder instance for your later use as you have mentioned in the question.
I think you will have to execute a raw query.
$result = DB::select("SELECT * FROM (
Select * from organizers
Order by organizers.rank
) Group by t.department");
reference: https://laravel.com/docs/5.7/queries#raw-expressions

how to write a mysql function in codeigniter join() method

I'm in big trouble in codeigniter.
I want to use FIND_IN_SET mysql function in codeigniter join() function. But problem is codeigniter consider FIND_IN_SET as a field name.
Please check below code:
$this->db->select("gcpo.promotional_offer_id,gcpo.promotional_offer_name,gcpo.promotional_offer_code,gcpo.promotional_offer_type,gcpo.promotional_offer_discount,gcpo.promotional_offer_min_amount,gcpo.promotional_offer_uses_per_offer,gcpo.promotional_offer_start_date,gcpo.promotional_offer_end_date,name,gcpo.promotional_offer_is_active,gcpo.promotional_offer_added_date,count(gcopo.promotional_offer_code) as cntP");
$this->db->from("promotional_offer gcpo");
$this->db->join("customer_groups", "FIND_IN_SET(id,promotional_offer_customer_group) > 0");
$this->db->join("order_promotional_offer gcopo", "gcopo.promotional_offer_code=gcpo.promotional_offer_code","left");
$this->db->group_by('gcpo.promotional_offer_code');
$this->db->limit($_GET['iDisplayLength'], $start);
$this->db->order_by($sort_array[$_GET['iSortCol_0']], $_GET['sSortDir_0']);
$query = $this->db->get();
In mysql query output which given by codeigniter:
SELECT `gcpo`.`promotional_offer_id`, `gcpo`.`promotional_offer_name`, `gcpo`.`promotional_offer_code`, `gcpo`.`promotional_offer_type`, `gcpo`.`promotional_offer_discount`, `gcpo`.`promotional_offer_min_amount`, `gcpo`.`promotional_offer_uses_per_offer`, `gcpo`.`promotional_offer_start_date`, `gcpo`.`promotional_offer_end_date`, `name`, `gcpo`.`promotional_offer_is_active`, `gcpo`.`promotional_offer_added_date`, count(gcopo.promotional_offer_code) as cntP FROM (`gc_promotional_offer` gcpo) JOIN `gc_customer_groups` ON `FIND_IN_SET`(`id,promotional_offer_customer_group)` > 0 LEFT JOIN `gc_order_promotional_offer` gcopo ON `gcopo`.`promotional_offer_code`=`gcpo`.`promotional_offer_code` GROUP BY `gcpo`.`promotional_offer_code` ORDER BY `gcpo`.`promotional_offer_added_date` desc LIMIT 10
now please find the find_in_set function in mysql query you will find like field name that consider by codeigniter .
FIND_IN_SET is a restriction function, you want to use it with a where. First you need to join customer_groups, and then restrict results with a where.
Change __PUT JOIN CONDITION HERE__ with your condition, and prefix FIND_IN_SET with correct table alias.
$this->db->select("gcpo.promotional_offer_id,gcpo.promotional_offer_name,gcpo.promotional_offer_code,gcpo.promotional_offer_type,gcpo.promotional_offer_discount,gcpo.promotional_offer_min_amount,gcpo.promotional_offer_uses_per_offer,gcpo.promotional_offer_start_date,gcpo.promotional_offer_end_date,name,gcpo.promotional_offer_is_active,gcpo.promotional_offer_added_date,count(gcopo.promotional_offer_code) as cntP");
$this->db->from("promotional_offer gcpo");
$this->db->join("order_promotional_offer gcopo", "gcopo.promotional_offer_code=gcpo.promotional_offer_code","left");
$this->db->join("customer_groups", "__PUT JOIN CONDITION HERE__");
$this->db->where("FIND_IN_SET(id,promotional_offer_customer_group) > 0");
$this->db->group_by('gcpo.promotional_offer_code');
$this->db->limit($_GET['iDisplayLength'], $start);
$this->db->order_by($sort_array[$_GET['iSortCol_0']], $_GET['sSortDir_0']);
$query = $this->db->get();

Join subquery with doctrine 2 DBAL

I'm refactoring a Zend Framework 2 application to use doctrine 2.5 DBAL instead of Zend_DB (ZF1). I have the following Zend_Db query:
$subSelect = $db->select()
->from('user_survey_status_entries', array('userSurveyID', 'timestamp' => 'MIN(timestamp)'))
->where('status = ?', UserSurveyStatus::ACCESSED)
->group('userSurveyID');
$select = $db->select()
// $selectColNames contains columns both from the main query and
// the subquery (e.g. firstAccess.timestamp AS dateFirstAccess).
->from(array('us' => 'user_surveys'), $selectColNames)
->joinLeft(array('firstAccess' => $subSelect), 'us.userSurveyID = firstAccess.userSurveyID', array())
->where('us.surveyID = ?', $surveyID);
This results in the following MySQL query:
SELECT `us`.`userSurveyID`,
// More columns from main query `us`
`firstAccess`.`timestamp` AS `dateFirstAccess`
FROM `user_surveys` AS `us`
LEFT JOIN (
SELECT `user_survey_status_entries`.`userSurveyID`,
MIN(timestamp) AS `timestamp`
FROM `user_survey_status_entries`
WHERE (status = 20)
GROUP BY `userSurveyID`
) AS `firstAccess` ON us.userSurveyID = firstAccess.userSurveyID
WHERE (us.surveyID = '10')
I can't figure out how to join the subquery using the doctrine 2.5 query builder. In the main query, I need to select columns from the subquery.
I have read here that doctrine does not support joining subqueries. If that's still true, can I write this query in another way using the SQL query builder of doctrine DBAL? Native SQL may not be a good solution for me, as this query will be dynamically extended later in the code.
I've found a solution by adapting this DQL example to DBAL. The trick is to get the raw SQL of the subquery, wrap it in brackets, and join it. Parameters used in the subquery must be set in the main query:
Important it's the createQueryBuilder of connection not the one of the entity manager.
$subSelect = $connection->createQueryBuilder()
->select(array('userSurveyID', 'MIN(timestamp) timestamp'))
->from('user_survey_status_entries')
// Instead of setting the parameter in the main query below, it could be quoted here:
// ->where('status = ' . $connection->quote(UserSurveyStatus::ACCESSED))
->where('status = :status')
->groupBy('userSurveyID');
$select = $connection->createQueryBuilder()
->select($selectColNames)
->from('user_surveys', 'us')
// Get raw subquery SQL and wrap in brackets.
->leftJoin('us', sprintf('(%s)', $subSelect->getSQL()), 'firstAccess', 'us.userSurveyID = firstAccess.userSurveyID')
// Parameter used in subquery must be set in main query.
->setParameter('status', UserSurveyStatus::ACCESSED)
->where('us.surveyID = :surveyID')->setParameter('surveyID', $surveyID);
To answer this part of your question:
I can't figure out how to join the subquery using the doctrine 2.5 query builder
You can make 2 query builder instances and use the DQL from the second one inside a clause of your first query. An example:
->where($qb->expr()->notIn('u.id', $qb2->getDQL())
Check examples here or here or find more using Google

CodeIgniter db select returns different result than SQL query

I wanted to use the CI Active Record methods to perform this query, but it gives me different results than if I execute the query in plain SQL. This is the query:
SELECT B.id as id
FROM default_log_workout A, default_log_workout B
WHERE A.id=$id AND B.completed < A.completed AND A.workout_id=B.workout_id
ORDER BY B.completed desc
LIMIT 1
CodeIgniter:
$this->db->select("B.id as id");
$this->db->from("log_workout A, log_workout B");
$this->db->where(array("A.id" => $id, "B.completed < A.completed", "A.workout_id=B.workout_id"));
$this->db->order_by("B.completed desc");
$this->db->limit(1);
$res = $this->db->get();
The query should return the next older row based on a given "id". The plain SQL works, the CI calls end up returning the OLDEST row, not the next oldest. I figure it's just a syntax error in my CI calls... but I can't figure it out. I've since moved on to solve the problem with $this->db->query("the SQL") but this is still bugging me.
Anyone know why the CI version doesn't work?
The ORDER BY clause should have two parameters:
$this->db->order_by('B.completed', 'DESC');
I'm not sure if Active Record will parse your comma separated table string in your from() clause. I suggest rewriting it in an ANSI standard from ... join ... on syntax.
$this->db->select("B.id as id");
$this->db->from("log_workout A");
$this->db->join("log_workout B","A.workout_id = B.workout_id AND B.completed < A.completed");
$this->db->where("A.id" => $id);
$this->db->order_by("B.completed", "desc");
$this->db->limit(1);
$res = $this->db->get();
And, as Yan pointed out, the order by should have two parameters.

Categories