Im having a problem when using the IN function of MySQL in a Laravel 5.2 DB Statement. Here is the example:
$str_array = implode(",",$array_reservations);
$sql_result = DB::select("
select r.id,r.people,r.date,r.status,p.alias,u.name,p.profile
from reservations r inner join places p on p.id = r.place_id
inner join users u on u.id = r.user_id
where r.id in(?)
order by r.date desc
", [$str_array]);
But in the result I just get the result of the first reservation of the array.
The length of the array will be always variable.
In this case you need to use DB::raw. Also, you need to create as many "?" you need, for each id you want to bind. That's the way PDO works:
$str_array = implode(",",$array_reservations);
$bindings = trim(str_repeat('?,', count($array_reservations)), ',');
DB::select($sql, $inputids);
$sql_result = DB::select(DB::raw("
select r.id,r.people,r.date,r.status,p.alias,u.name,p.profile
from reservations r inner join places p on p.id = r.place_id
inner join users u on u.id = r.user_id
where r.id in($bindings)
order by r.date desc
"), $str_array);
But, IMO, you should use Query Builder:
DB::table('reservations')
->join('places','places.id','=','reservarions.place_id')
->join('users','users.id','=','reservarions.user__id')
->whereIn('reservations.id',$str_array)
->orderBy('reservations.date', 'DESC');
Try this :
$sql_result = DB::table('reservations AS r')
->join('places AS p', 'p.id', '=', 'r.place_id')
->join('users AS u', 'u.id', '=', 'r.user_id')
->select('r.id','r.people','r.date','r.status','p.alias','u.name','p.profile')
->whereIn('r.id',$str_array) // write you conditions in array
->orderBy('r.date', 'desc')
->get();
Related
The following query runs just fine when I paste it into my SQL tool, but through Laravel, it returns zero rows.
$sql = "
SELECT main_query.* FROM (
SELECT
c.id,
c.name,
c.order,
cd.case,
(SELECT count(*) from logs cl
where
c.id = cl.id
and cl.status = 'OPEN'
) as cl_count,
sdsc.task
FROM `table` c
INNER JOIN `table2` cd ON (c.id = cd.id)
LEFT JOIN `table3` sdsc ON (c.id = sdsc.id)
WHERE
c.status = 'NEW'
GROUP BY c.id
ORDER BY cd.updated_at DESC
) main_query
where main_query.cl_count > 1
GROUP BY main_query.id
ORDER BY main_query.updated_at DESC
limit 0,20
";
Due to the complexity of the actual query, I cannot convert it wholly into an eloquent query, so I am executing it using DB::select(DB::raw($searchQuery));
If I remove where main_query.cl_count > 1, the query runs just fine. What is causing this to fail, and how do I rewrite the code?
Try below code, generated by https://sql2builder.github.io/
DB::query()->fromSub(function ($query) {
$query->from('table')
->select('table.id', 'table.name', 'table.order', 'table2.case', 'table3.task')
->on(function ($query) {
$query->where('table.id','=','table2.id');
})
->on(function ($query) {
$query->where('table.id','=','table3.id');
})
->where('table.status','=','NEW')
->groupBy('table.id')
->orderBy('','desc');
},'main_query')
->select('main_query.*')
->where('main_query.cl_count','>',1)
->groupBy('main_query.id')
->orderBy('','desc')
->get();
I am new to Laravel and trying to support an existing application that is in Laravel 5. I am trying to convert the following SQL to eloquent structure
SELECT s.id,
CONCAT(u.first_name, ' ', u.last_name) AS user_name,
u.avatar_location AS user_img,
s.employee_photo,
d.name AS department,
seg.name AS segment,
s.survey_title,
s.before_action,
s.before_picture,
s.action,
s.action_date,
s.after_action,
s.after_picture,
s.nominated,
s.awarded,
s.created_at,
s.updated_at,
(SELECT COUNT(1) FROM likes l WHERE l.survey_id = s.id) AS likes,
(SELECT COUNT(1) FROM likes l WHERE l.survey_id = s.id AND l.user_id = 5) AS UserLikes,
(SELECT COUNT(1) FROM comments c WHERE c.survey_id = s.id ) AS comments
FROM surveys s
JOIN departments d
ON s.department = d.id
JOIN segments seg
ON s.segment_id = seg.id
JOIN users u
ON s.user_id = u.id
WHERE s.status = 'Approved'
ORDER BY s.action_date DESC
LIMIT 20 OFFSET 20
I know enough Laravel to know that my basic start would probably be
$surveys = DB::table('surveys')
->join('departments', 'surveys.department', '=', 'departments.id')
->join('segments', 'surveys.segment_id', '=', 'segments.id')
->join('users', 'surveys.user_id', '=', 'users.id')
->where('surveys.status', 'Approved')
->orderBy('surveys.action_date')
->skip(20)-take(20)
->select(...)->get();
However, I am not sure how to do the subqueries. Looking for any suggestions.
Thanks!
For select statements, you can use DB::raw().
$surveys = DB::table('surveys')
->join('departments', 'surveys.department', '=', 'departments.id')
->join('segments', 'surveys.segment_id', '=', 'segments.id')
->join('users', 'surveys.user_id', '=', 'users.id')
->where('surveys.status', 'Approved')
->orderBy('surveys.action_date')
->skip(20)-take(20)
->select([DB::raw('(SELECT COUNT(1) FROM likes l WHERE l.survey_id = s.id) AS likes'),
...
])
->get();
Similarly, select statements would go under the select array. Just so to be clear, the result will be a collection.
Im tried this to work it using Laravel Eloquent but i cant get exact query. So i make a raw query to get the data i want. Any one help me how to convert this into laravel eloquent or Query builder?
SELECT users.*,
chat.*
FROM users
LEFT JOIN
(SELECT a.customer_id,
a.time,
b.content
FROM
(SELECT customer_id,
MAX(datetimestamp) TIME
FROM chat_messages
GROUP BY customer_id) a
JOIN chat_messages b ON a.customer_id = b.customer_id
AND a.time = b.datetimestamp) chat ON users.id = chat.customer_id
WHERE users.customer_role != 0
ORDER BY TIME DESC
I think you are trying to get latest chat message for each user , your query can be rewritten using left join to pick the latest record per group and it would be easier to transform such query in laravel's query builder format
SQL
select u.*,c.*
from users u
join chat_messages c on u.id = c.customer_id
left join chat_messages c1 on c.customer_id = c1.customer_id and c.datetimestamp < c1.datetimestamp
where c1.customer_id is null
and u.customer_role != 0
order by c.datetimestamp desc
Query Builder
DB::table('users as u')
->select('u.*, c.*')
->join('chat_messages as c', 'u.id', '=', 'c.customer_id' )
->leftJoin('chat_messages as c1', function ($join) {
$join->on('c.customer_id', '=', 'c1.customer_id')
->whereRaw(DB::raw('c.datetimestamp < c1.datetimestamp'));
})
->whereNull('c1.customer_id')
->where('u.customer_role','!=',0)
->orderBy('c.datetimestamp', 'desc')
->get();
Reference:Laravel Eloquent select all rows with max created_at
I am trying to pass following sql query to Doctrine:
SELECT id, name, count(*) FROM (SELECT r.id, r.name, f.timestamp FROM `food_log` as f inner join recipe as r on f.recipe_id = r.id WHERE f.user_id = 6 and timestamp > "2016-09-01" and recipe_id is not null group by f.timestamp, r.id) a GROUP BY a.id ORDER BY count(*) DESC
It should return me recipes with amount of how many times particular user was using single recipe from selected timestamp.
Now I am trying to do this with Doctrine 1.2 and Symfony 1.4, however I do not know how to make query from subquery, I was trying to do something like this
$subQuery = Doctrine_Query::create()
->select('r.id, r.name, f.timestamp')
->from('FoodLog f')
->innerJoin('f.Recipe r')
->where('f.user_id = ?', $userId)
->andWhere('timestamp > ?', "2016-09-01")
->andWhere('f.recipe_id is not null')
->andWhere('r.is_premium = ?', $premium)
->groupBy('f.timestamp, r.id')
->getSqlQuery();
$query = Doctrine_Query::create()
->select('id, name, count(*)')
->from($subQuery)
->groupBy('id')
->orderBy('count(*) DESC');
return $query->fetchArray();
Anybody know where I am wrong with it ?
Thanks a lot for any response !
Basically, you can't do nested queries in this version of Doctrine. I'd recommend using a raw SQL query via the doctrine connector:
$sql = 'SELECT id, name, count(*) FROM (SELECT r.id, r.name, f.timestamp FROM `food_log` as f inner join recipe as r on f.recipe_id = r.id WHERE f.user_id = 6 and timestamp > "2016-09-01" and recipe_id is not null group by f.timestamp, r.id) a GROUP BY a.id ORDER BY count(*)
DESC';
$conn = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $conn->execute($sql);
foreach($result as $data){
// do something
}
As you're not hydrating objects, you should find this works well.
I have 2 tables.
table 1 (projects): id, name, type
table 2 (project_ratings): project_id, rating
Some projects don't have ratings.
SELECT `p`.`id`, `p`.`name`, AVG(pr.rating) FROM (`projects` p) JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id` WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';
I want to return all projects, and return NULL if there aren't any ratings. This query returns only the ones with ratings.
I tried left join, right join, full join, still same thing.
Using CodeIgniter Active Records:
$this->db->select("p.id, p.name, AVG(pr.rating)");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id');
$this->db->where('p.type', 'group');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();
what am I missing?
When using an aggregate function (AVG() in this case), you need to specify a GROUP BY clause with the non-aggregate fields, eg
GROUP BY p.id, p.name
To ensure all project references are present regardless of joined ratings, use a LEFT JOIN.
The sql that you want would be
SELECT *
FROM projects
LEFT OUTER JOIN project_ratings ON projects.id = project_ratings.project_id
I'm not certain how to do that with code igniter.
Try this:
$this->db->select("p.id, p.name, AVG(pr.rating) as average_rating");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'left');
$this->db->where('p.type', 'group');
$this->db->group_by('p.id');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();
If there is no rating, average_rating will be NULL.
Query should be:
SELECT `p`.`id`, `p`.`name`, AVG(pr.rating)
FROM (`projects` p)
LEFT OUTER JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id`
WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';
(I don't know how to do that in CodeIgniter :)
You can get an outer join by do this:
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'outer');