Distinct and orderby doctrine querybuilder - php

I have the following query that I need to get working:
$repository = $this->getDoctrine()->getRepository('AppBundle:ProjectPhaseUser');
$query = $repository->createQueryBuilder('p')
->select('(p2.project) AS projectId')
->leftJoin('AppBundle:ProjectPhase', 'p2', 'WITH', 'p.projectPhase = p2.id')
->where('p.user = ' . $user->getId())
->orderBy('p.assignDate', 'DESC')
->setMaxResults(3)
->getQuery();
Basically there are 2 tables: ProjectPhaseUser and ProjectPhase
What resides in the ProjectPhaseUser table are the users with projectphases and an assigndate. In the ProjectPhase table you have the projectphases and projects they belong to.
What I want is to get the 3 last assigned projects of a particular user.
What the query does now is get the last 3 projectphases their projects. However this gives me duplicate projects since a project can have multiple projectphases. When I try a distinct on the project I get the problem that orderby is not in the select clause. I also have tried groupby which gives me the only full group by mysql error.
How can I achieve this without altering the mysql only full group by option?

Related

What is wrong with this laravel query with left join?

I am working on a laravel project(Laravel 6.8). I have a locations table and a dashboards table. I am trying to build a query that will return all matching records from the dashboards table. Looking at another SO question(Laravel 5.4 Raw Join Query), I saw a similar need and tried to adjust the code to fit my needs, but it still doesn't work.
This is what I have right now.
$locations = DB::table('locations')
->selectRaw("site_name,
COUNT(DISTINCT client) as client_count,
GROUP_CONCAT(client_lob) as lobs,
COUNT(DISTINCT client_lob) as lob_count,
SUM(agent_workstations) as aw_sum,
SUM(production_support_workstations) as psw_sum,
locations.*" )
->leftJoin('dashboards', 'locations.id', '=', 'dashboards.location_id')
->whereNotNull('latitude')
->groupBy(['site_name'])
->orderBy('site_name', 'asc')
->get();
It returns only the data from locations without returning anything from dashboards. I can't see what is wrong with this query. Can anyone offer some advice?
Because you never select the dashboard's fields, try to select the dashboard's field like this:
$locations = DB::table('locations')
->selectRaw("site_name,
COUNT(DISTINCT client) as client_count,
GROUP_CONCAT(client_lob) as lobs,
COUNT(DISTINCT client_lob) as lob_count,
SUM(agent_workstations) as aw_sum,
SUM(production_support_workstations) as psw_sum,
locations.*, dashboards.column1, dashboards.column2" )

Laravel orwhere and whereBetween query not working together

I have a situation to filter user from database in a way that to filter from two columns of the table with a particular id and that should be filtered with a range of date.
My code is as shown below.
$fetchSelectedUser=Wallet_Transaction::select('wallet__transactions.from as FromUser','wallet__transactions.type','wallet__transactions.date','wallet__transactions.amount','wallet__transactions.balance_after',
'wallet__transactions.type','wallet__transactions.description','wallet__transactions.to as ToUser','users.name as FromName',DB::raw('(select name from users where users.id = ToUser) as toName'))
->join('users','users.id','=','wallet__transactions.from')
->where('wallet__transactions.from','=',$user_id)->orWhere('wallet__transactions.to','=',$user_id)
->whereBetween('wallet__transactions.db_date',[$fromDate,$toDate])->get();
what I have tried is put a static date, and is not working. Also I removed orWhere and whereBetween independently. That is working. But it will not working together.
Use where() closure to group your conditional query:
$fetchSelectedUser=Wallet_Transaction::select('wallet__transactions.from as FromUser','wallet__transactions.type','wallet__transactions.date','wallet__transactions.amount','wallet__transactions.balance_after',
'wallet__transactions.type','wallet__transactions.description','wallet__transactions.to as ToUser','users.name as FromName',DB::raw('(select name from users where users.id = ToUser) as toName'))
->join('users','users.id','=','wallet__transactions.from')
->where(function($q) use ($user_id){
$q->where('wallet__transactions.from','=',$user_id)->orWhere('wallet__transactions.to','=',$user_id);
})->whereBetween('wallet__transactions.db_date',[$fromDate,$toDate])->get();

How can I retrieve the information I want using MySQL `joins` or Laravel `relationships`?

I am working on a project using the Laravel framework. In this project I have three tables:
1) Master Part Numbers (master_part_numbers)
Columns: id, part_number
Values: 1, MS26778-042
2) Inventory (inventory)
Columns: id, master_part_number, stock_qty
Values: 1, 1, 7
3) Inventory Min Maxes (inventory_min_maxes)
Columns: id, master_part_number, min_qty
Values: 1, 1, 10
I am trying to find the inventory where the stock level is below the min_qty. I have been attempting this using joins, like so:
$test = MasterPartNumber::table('master_part_numbers')
->join('inventory', 'master_part_numbers.id', '=', 'inventory.master_part_number_id')
->join('inventory_min_maxes', 'master_part_numbers.id', '=', 'inventory_min_maxes.master_part_number_id')
->select('master_part_numbers.part_number')
->where('inventory.stock_qty', '<=', 'inventory_min_maxes.min_qty')
->get();
However I am getting an empty collection every time. I have tried removing the where() clause and I get all the part numbers in the inventory, so it feels like I'm on the right track, but missing a critical component.
Also, I don't know if there is an easier or more efficient way to do this using Laravel's Eloquent Relationships, but that option is available.
Note: I added the space after table('master_part_numbers') in my query displayed here on purpose, for readability.
EDIT 1:
This sql query returns the expect result:
SELECT master_part_numbers.part_number
FROM master_part_numbers
JOIN inventory ON master_part_numbers.id=inventory.master_part_number_id
JOIN inventory_min_maxes ON master_part_numbers.id=inventory_min_maxes.master_part_number_id
WHERE inventory.stock_qty<=inventory_min_maxes.min_qty;
EDIT 2:
I finally got it working with some help from the Laravel IRC, however it isn't ideal because I am missing out on some of the data I would like to display, normally collected through relationships.
Here is what I am currently using, but I hope to get refactored:
DB::select(DB::raw('SELECT master_part_numbers.id, master_part_numbers.part_number, master_part_numbers.description, inventory.stock_qty, inventory.base_location_id, inventory_min_maxes.min_qty, inventory_min_maxes.max_qty
FROM master_part_numbers
JOIN inventory ON master_part_numbers.id = inventory.master_part_number_id
JOIN inventory_min_maxes ON master_part_numbers.id = inventory_min_maxes.master_part_number_id
WHERE inventory.stock_qty <= inventory_min_maxes.min_qty'));
If I have understood your problem correctly then
'masters_part_numbers.id' == 'inventory.id' and
'inventory.master_part_number' == 'inventory_min_maxes.master_part_number'
$test = DB::table('master_part_numbers')
->join('inventory', 'master_part_numbers.id', '=', 'inventory.id')
->join('inventory_min_maxes', 'inventory.master_part_number', '=', 'inventory_min_maxes.master_part_number')
->where('inventory.stock_qty', '<=', 'inventory_min_maxes.min_qty')
->whereNotNull('inventory_min_maxes.master_part_number');
->select(DB::raw('part_number'))
->get();
Based on above criteria. This code will work. I tried in laravel 5.4 .
Try and let me know. nd if it work give me a thumbs up
I discovered a way to solve this problem using the Laravel ->whereRAW() statement:
$test = $inventory->join('inventory_min_maxes', 'inventory.id', '=', 'inventory.inventory_min_max_id')
->whereRaw('inventory.stock_qty <= inventory_min_maxes.min_qty')
->whereRaw('inventory.inventory_min_max_id = inventory_min_maxes.id') // required so it tests against the specific record, without it will test against all records.
->get();
The major advantage for me, other than it looked terribly ugly before, was that I can now use the power of relationships.
Note: $inventory is an instance of my Inventory model, which I type hinted in the index() method.

Symfony Doctrine Query Builder Where last in arraycollection

I want to use symfony's query builder and add a where to the last item in an array collection
$query = $em->getRepository('RlBookingsBundle:Booking')->createQueryBuilder('b')
->select('b, v, c, ca, q')
->leftJoin('b.vehicle', 'v')
->leftJoin('b.customer', 'c')
->leftJoin('c.address', 'ca')
->leftJoin('b.quote', 'q')
->leftJoin('b.history', 'h') //This is an array collection
->orderBy('b.edited', 'DESC')
;
I want to use only the latest value from history as it is a log but only the most recent entry is valid
->where('h.status IN (:status)')
->setParameter('status', [7]);
Will return all results with h.status = 7 but I would like it to only query the most recent result. Is there anyway to do this?
I tried a groupby on the history field but this seems to groupby with data from the first entry, even if I add an orderby to it.
If the results you get are already ok, but you only want the first, you could just use
...
->setMaxResults(1)
...
If you want to order by history ID desc, you may want to add another orderBy clause before the existing one
...
->orderBy('h.id', 'DESC')
->orderBy('b.edited', 'DESC')
...
If it's more complex than that, I strongly suggest you perform a separate query to get the desired record(s) from history, and THEN use it as a filter, instead of the leftJoin.

Empty where clause in Laravel 5.1 preferring eloquent method

i am looking to produce the following query in laravel 5.1 with eloquent method.
The mysql query is a follows
SELECT * FROM orders WHERE 1 = 1 ORDER BY o_date DESC LIMIT 25
No matter what i cant get the
WHERE 1 = 1
part working.
am new to laravel and pretty sure this is easy. but can't figure it out.
I have tried the following variations
$orders = orders::where('1', 1)->orderBy('o_date', 'desc')->take(25)->get();
$orders = orders::where(1)->orderBy('o_date', 'desc')->take(25)->get();
$orders = orders::where('1', '=', '1')->orderBy('o_date', 'desc')->take(25)->get();
but its not working. the query results is as shown below
> select count(*) as aggregate from `orders`
Seems like (looking at 1=1) you need whereRaw
$orders = orders::whereRaw("any clause u wish")->orderBy('o_date', 'desc')->take(25)->get();
but if "any clause u wish" is not a VERY-VERY dinamical part u'd better look what else you can use
http://laravel.com/api/5.0/Illuminate/Database/Query/Builder.html
For the above example the below code works fine
$orders = orders::whereRaw("1 = 1")->orderBy('o_date', 'desc')->take(25)->get();
Why do you want to create a condition that will be always true? I think that Eloquent is smart enought to remove this useless part of the query.

Categories