Laravel query using group by and where does not work - laravel

This is a query that I have in raw sql.
DB::select('SELECT bldgs.name as building , floors.name as floor, areas.name as area, locations.area_id ,count(reqs.location_id) as occupied FROM `reqs` '
. 'JOIN locations ON locations.id = location_id '
. 'JOIN areas ON areas.id = area_id '
. 'JOIN floors ON floors.id = areas.floor_id'
. ' JOIN bldgs ON bldgs.id = bldg_id '
. 'WHERE `status`=2 and (DATE_FORMAT(start_date,"%Y-%m")<= "'.$dateFrom.'" AND DATE_FORMAT(end_date,"%Y-%m")>="'.$dateTo.'") group by locations.area_id, areas.name, floors.name, bldgs.name' );
And this is one of many attempts to make it work in Laravel elequent instead of raw.
Req::select('bldgs.name as building',DB::raw('count(location_id) as count_occupied'))
->join('locations','locations.id','=','location_id')
->join('areas','areas.id','=','locations.area_id')
->join('floors','floors.id','=','areas.floor_id')
->join('bldgs as bl','bl.id','=','floors.bldg_id')
->where('reqs.status','=', '2')
->where('start_date','<=', $date)
->where('end_date','>=', $date)
->groupBy('bldgs.name')
I need to understand why the second way gives mysql error and refuses to run the query above. Is is a mistake in my code or is this normally not possible in using eloguent to group by like this except in raw mysql string?
This is the error I get.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'bldgs.name' in 'field list' (SQL: select `bldgs`.`name` as `building`, count(location_id) as count_occupied from `reqs` inner join `locations` on `locations`.`id` = `location_id` inner join `areas` on `areas`.`id` = `locations`.`area_id` inner join `floors` on `floors`.`id` = `areas`.`floor_id` inner join `bldgs` as `bl` on `bl`.`id` = `floors`.`bldg_id` where `reqs`.`status` = 2 and `start_date` <= 2018-10 and `end_date` >= 2018-10 group by `bldgs`.`name`)

As the error states, you don't have a bldgs.name column. You named the bldgs table bl when you joined it.
Rename your references from bldgs.name to bl.name.

Related

Laravel : Get records from a table with 'where clause' from a field in another table

i have two tables . first is 'projects' with field id,name,number and second table is 'happenings' with fields id,project_id . these tables have one-to-many relationship . How can i get records from 'happenings' where their 'number' field in 'projects' is for example 5 .
Try something like :
SQL query :
SELECT *, round(AVG(h.progress),0) as Progress FROM happenings h
JOIN projects p on p.id = h.project_id
WHERE p.number = 5
Eloquent :
$data = DB::table('happenings as h')
->join('projects as p','p.id', '=', 'h.project_id')
->select('*', DB::raw('round(AVG(h.progress),0) as Progress'))
->where('p.number','=',5)
->get();

Laravel Eloquent: how to use “where” with WithCount to select Models whose count is larger than a number

Suppose I have two tables: posts and tags. I want to eager load all the tags with posts whose post count is larger than 10. How would I do it?
I tried the following but not work:
Tag::withCount('posts')
->where('posts_count', '>' , 10)
->get();
It gives me the following error:
Column not found: 1054 Unknown column 'posts_count' in 'where clause' (SQL: select `tags`.*, (select count(*) from `posts` inner join `post_tag` on `posts`.`id` = `post_tag`.`post_id` where `tags`.`id` = `post_tag`.`tag_id`) as `posts_count` from `tags` where `posts_count` > 1 order by `posts_count` desc)
try this:
Tag::withCount('posts')->having('posts_count', '>' , 10)->get();
If you want to filter on aggregates, you need to use having.

Convert SQL to Laravel Eloquent Statement

I've been working on a few tables where through a rather complex relationship (that I'm trying to clean up, but I still need reports made from the data through my Laravel).
At the moment, I can pull the data using the following SQL query to my MySQL database:
SELECT
customers.id,
customers.customer_name,
SUM(shipments.balance) AS shipmentBalance
FROM customers
LEFT JOIN shipments
ON customers.id = shipments.bill_to
AND balance > (SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = pro_number)
GROUP BY customers.id, customers.customer_name
ORDER BY shipmentBalance DESC
LIMIT 5;
I'm just not sure how to rewrite it properly into the whereRaw or DB::raw statements that Laravel Eloquent requires, as my previous attempts have failed.
Update
Here is the closest solution I have tried:
DB::table('customers')
->select('customers', DB::raw('SUM(shipments.balance) AS shipmentBalance'))
->leftJoin(
DB::raw('
(select shipments
ON customers.id = shipments.bill_to
AND balance > (SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = pro_number)'))
->groupBy('customers.id')
->orderByRaw('shipmentBalance DESC')
->limit(5)
->get();
Update 2
Edit for Dom:
Using everything as it stands with your answer, I get the following response:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '' in 'on clause' (SQL: select customers.id, customers.customer_name,SUM(s.balance) AS shipmentBalance from `customers` left join `shipments` as `s` on `customers`.`id` = `s`.`bill_to` and s.balance > (SELECT IFNULL(SUM(payments_distributions.amount),0) FROM payments_distributions WHERE payments_distributions.shipment_id = s.pro_number) = `` group by `customers`.`id`, `customers`.`customer_name` order by SUM(s.balance) DESC limit 5)
But if I remove this section, it brings up the page and the customers (though in the wrong order as I have removed one of the necessary components:
$join->on(DB::raw('s.balance >
(SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = s.pro_number)
'));
Is there anything I can provide you with to get this specific statement to work with your entire answer?
Use this:
DB::table('customers')
->select('customers.id', 'customers.customer_name', DB::raw('SUM(shipments.balance) AS shipmentBalance'))
->leftJoin('shipments', function($join) {
$join->on('customers.id', 'shipments.bill_to')
->where('balance', '>', function($query) {
$query->selectRaw('IFNULL(SUM(payments_distributions.amount),0)')
->from('payments_distributions')
->where('payments_distributions.shipment_id', DB::raw('pro_number'));
});
})
->groupBy('customers.id', 'customers.customer_name')
->orderByDesc('shipmentBalance')
->limit(5)
->get();
Without the Models containing relationships or being able to test on this specific project, this is the most eloquent way I can think of performing your task.
The benefit of starting with the Customer model is you will have a laravel collection and can paginate as needed. Also review the eloquent docs, they help you understand all the different options. Hope his helps.
P.S. Start by using your model in your controller or wherever you are placing this query with:
use App\Customer
The query
$theQuery = Customer::select(DB::raw('customers.id, customers.customer_name,SUM(s.balance) AS shipmentBalance'))
->leftJoin('shipments as s', function($join)
{
$join->on('customers.id', '=', 's.bill_to');
$join->on(DB::raw('s.balance >
(SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = s.pro_number)
'));
})
->groupBy('customers.id', 'customers.customer_name')
->orderByRaw('SUM(s.balance) DESC')
->limit(5)
->get();

Subqueries in Doctrine 1.2 DQL as FROM

Ok so the big deal is to get the rows in a mysql table that have another related row in the same table given some conditions. This table is like an activity log, so i want to notify someone that "some guy" leaved his group, but i only want do the notification when that guy joined the group before a given date, so what i do is the next sql:
SELECT ua.*, ua2.*
FROM user_activities AS ua
INNER JOIN (SELECT ua2.* FROM user_activities AS ua2
WHERE ua2.activity = "join-group"
ORDER BY ua2.created_at)
AS ua2 ON ua2.group_name = ua.group_name AND ua2.user_id = ua.user_id
WHERE ua.activity = "unjoin-group";
I omitted the date conditions due to clarity reasons.
So i need to know how to convert this to DQL (for doctrine 1.2), is it possible? or I better do it programatically?
What im trying now is this:
$q = Doctrine_Query::create()
->from('UserActivity ua, ua.User u ')
->where('ua.created_at > ?', $min_date)
->andWhere('ua.activity = ?', "unjoin-group")
->andWhereIn('u.status', array(STATUS_HOT, STATUS_ACTIVE))
->andWhere('ua.user_id IN ( SELECT
uaa.id
FROM
UserActivity uaa
WHERE
uaa.activity = ? AND
uaa.created_at < ? AND
uaa.created_at > ? AND
uaa.group_name = ua.group_name
LIMIT 1',
array("join-group", $min_date, $max_date));
But i get this error:
fatal error maximum function nesting level of '100' reached aborting
So i can't keep foward

Unknown column - multiple joins in CDbCriteria

I'm trying to get data from multiple tables and I've ended with this error:
SQL: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'p.firstname' in 'field list'
$criteria = new CDbCriteria;
$criteria->select = 'ohu_id, hash, p.firstname, p.surname, p.city, u.email AS Email';
$criteria->join = 'LEFT JOIN `profiles` p ON p.user_id = user_id';
$criteria->join = 'LEFT JOIN users u ON user_id = u.id';
$criteria->condition = 'offer_id = :oID';
$criteria->params = array(':oID' => $_GET['id']);
$model = MyModel::model()->findAll($criteria);
Anyone know what I'm doing wrong?
Or is there better way to get related data?
You are making the same mistake I made hehe.
You are overwriting the first join with the second one, instead of appending the second join.
$criteria->join = "join ...."; //first join
$criteria->join .= "join ...."; //second join
cheers
Actually its way better to user some "with" clause like this:
$criteria->with = array(
'profiles '=>array(
'select'=>'profiles.user_id',
'together'=>true
),
'users'=>array(
'select'=>'users.id',
'together'=>true
)
);
You can use this also in model searching for CGridView DataProvider.
It's better if you show your database structure. But here it's the solution to join multiple tables using left join
Code to join tables:
$criteria->select = 'ohu_id, hash, p.firstname, p.surname, p.city, u.email AS Email';
$criteria->alias = 'c';
$criteria->join = 'LEFT JOIN profiles p ON (p.user_id = c.user_id) LEFT JOIN users u ON (c.user_id = u.id)';
Hope it will help you.

Resources