Doctrine orderBy with NULL last - sorting

I have a table with items I have to sort, where some items having statuses. What I need is:
Sort items by status' 'sort' values (ASC)
Sort items by timestamp (DESC)
Sort all items so that all items without status are last but also sorted by timestamp
Here's what I have:
$query->leftJoin('c', 'Statuses', 'st', 'st.id = c.status')
->addSelect('CASE WHEN c.status IS NULL THEN 1 ELSE 0 END as HIDDEN status_is_null')
->orderBy('status_is_null', 'asc')
->addOrderBy('st.sort', 'asc')
->addOrderBy('c.timestamp', 'desc');
But it throws an error:
An exception occurred while executing 'SELECT c.id, CASE WHEN c.status IS NULL THEN 1 ELSE 0 END as HIDDEN status_is_null FROM Items c WHERE c.active = ? ORDER BY status_is_null asc, c.timestamp desc LIMIT 10 OFFSET 0' with params [true]: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'status_is_null FROM Items c WHERE c.active = '1' ORDER BY ' at line 1
What am I doing wrong?

Related

Laravel ambiguous key in 'where' clause

I have a customer class and a pet class which has a many to many relationship. There is a pivot table customer_pet. Both the customers table and the pets table have a team_id.
When I write the following code:
$results = auth()->user()->team->customers();
$results->leftJoin('customer_pet', 'customer_pet.customer_id', '=', 'customers.id');
$results->leftJoin('pets', 'pets.id', '=', 'customer_pet.pet_id');
return $results->get()->load('pets');
I get this error:
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'team_id' in where clause is ambiguous (SQL: select * from `customers` left join `customer_pet` on `customer_pet`.`customer_id` = `customers`.`id` left join `pets` on `pets`.`id` = `customer_pet`.`pet_id` where `customers`.`team_id` = 2 and `customers`.`team_id` is not null and `customers`.`deleted_at` is null and `team_id` = 2
I tried making the relation in the Customer model look like this:
public function team()
{
return $this->belongsTo(Team::class, 'customers.team_id', 'teams.id');
}
but I get the same result. I am missing something obvious but I am not sure what?
Any help would be appreciated. Thanks.
select * from `customers` left join `customer_pet` on `customer_pet`.`customer_id` = `customers`.`id` left join `pets` on `pets`.`id` = `customer_pet`.`pet_id` where `customers`.`team_id` = 2 and `customers`.`team_id` is not null and `customers`.`deleted_at` is null and `team_id` = 2
The query in the exception shows that there is a team_id = 2 at the end. It seems that you're adding a $query->where('team_id', 2) without qualification somewhere in your code.
You can use $query->qualifyColumn($column) to prepend the table name automatically.

Query on a view ,Postgres and Laravel

I try to do a query on a view from DB, with Laravel but I get an error, and I am not sure why.
ViewData::query()->where('page', '=', '918');
"SQLSTATE[42601]: Syntax error: 7 ERROR: zero-length delimited
identifier at or near """"↵LINE 1: ...data" where "page" = $1 order by
"view_full_data"."" asc lim...↵
^ (SQL: select * from "view_full_data" where "page" = 918 order by
"view_full_data"."" asc limit 1000 offset 0)"
From Postgres, a working one.
Select * from view_full_data where "page = 918;
I found the problem.
From Maatwebsite\Excel I get an order_by that is not ok (Maybe because I don't have an ID column).
I had to add orderBy manually.
ViewData::query()->where("page", '=', "918")->orderBy('page', 'asc');

Oracle query failed: missing right parenthesis

I have this query executed on ORACLE SGBD
update product p set p.PROVIDER_ID =
( select PROVIDER_ID from provider pr where pr.VALID_FROM is not null
and ((pr.VALID_TO is not null and pr.VALID_TO < p.VALID_TO )
or (pr.VALID_TO is null and pr.VALID_FROM < p.VALID_TO) )
and rownum < 2 order by valid_to desc
)
where p.VALID_FROM is not null and p.VALID_TO is not null;
Executing this query I get this error:
[UPDATE - 0 row(s), 0.000 secs] [Error Code: 907, SQL State: 42000] ORA-00907: missing right parenthesis.
I'm blocked at this point.
This is almost a duplicate of this, as the immediate problem is that you have an order by clause in a subquery - that isn't allowed and is causing this error. Oracle is expecting to see the closing parenthesis of the subquery after the rownum < 2.
But in this case it's slightly more complicated because you need the order by to get the desired row to match against, and you've got the rownum check in the wrong place; even as a standalone query that wouldn't give you the result you expect as it would find one indeterminate row and then order that single row, which is meaningless.
You need another layer, so your subquery has an inline view which can be ordered, and then you get the first row from that:
update product p set p.PROVIDER_ID =
(
select PROVIDER_ID from (
select pr.PROVIDER_ID from provider pr
where pr.VALID_FROM is not null
and ((pr.VALID_TO is not null and pr.VALID_TO < p.VALID_TO)
or (pr.VALID_TO is null and pr.VALID_FROM < p.VALID_TO))
order by pr.VALID_TO desc
)
where rownum < 2
)
where p.VALID_FROM is not null and p.VALID_TO is not null;
But now you'll get ORA-00904: "P"."VALID_TO": invalid identifier because you're trying to correlate the update by referencing columns from the p alias two levels down, which Oracle doesn't allow.
An alternative is to use analytics, such as keep dense_rank:
update product p set p.PROVIDER_ID =
(
select max(pr.PROVIDER_ID) keep (dense_rank first order by pr.VALID_TO desc)
from provider pr
where pr.VALID_FROM is not null
and ((pr.VALID_TO is not null and pr.VALID_TO < p.VALID_TO)
or (pr.VALID_TO is null and pr.VALID_FROM < p.VALID_TO))
)
where p.VALID_FROM is not null and p.VALID_TO is not null;
... which does run successfully. (I'm not entirely sure about your date comparison logic but that's a separate issue, and may actually be what you want).

how to pass select subquery in where clause using laravel

This is my SQl query
select sum(stock.total_in_stock) as total_in_stock
,stock.name
,stock.inventory_id
from (
select i.store_id
,i.model_id
,i. total_in_stock
,i.id as inventory_id
, m.*
from `inventory` as `i`
left join `model_store` as `ms` on `ms`.`store_id` = `i`.`store_id`
left join `model` as `m` on `m`.`id` = `ms`.`model_id`
where `i`.`model_id` = m.id
and `m`.`status` = 1
and `ms`.`status` = 1
and `i`.`created_at` = (
select si.created_at
from inventory AS si
where si.model_id = i.model_id
and si.store_id = i.store_id
and si.status=1
order by si.created_at desc limit 1
)
) as stock
group by stock.model_id
In laravel, it is written as this:
$results1 = DB::table('inventory as i')
->select(DB::raw( 'sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* '))
->leftJoin('model_store as ms','ms.store_id','=','i.store_id')
->leftJoin('model as m','m.id','=','ms.model_id')
->where('i.model_id','=', 'm.id')
->where('m.status','=', '1')
->where('ms.status','=', '1')
->where("i.created_at","=",function($query) {
$query->select(DB::raw("si.created_at FROM inventory AS si WHERE si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1)) as stock GROUP BY stock.model_id"));
});
It gives me the following error:-
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 (SQL: select sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* from `inventory` as `i` left join `model_store` as `ms` on `ms`.`store_id` = `i`.`store_id` left join `model` as `m` on `m`.`id` = `ms`.`model_id` where `i`.`model_id` = m.id and `m`.`status` = 1 and `ms`.`status` = 1 and `i`.`created_at` = (select si.created_at FROM inventory AS si WHERE si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1 )) as stock GROUP BY stock.model_id))
It takes 2 closing brackets at the end and gives the above error. Please help me writing the above SQL query in laravel.
Answering your question that's in the tile: the subquery where needs fix:
->where("i.created_at", function($query) {
$query->from('inventory as si')
->selectRaw('max(si.created_at)')
->whereRaw('si.model_id = i.model_id AND ...');
});
However, in order to create a subquery in the from clause, you need to pass raw query, so your whole code requires a bit of toSql() and setBindings(...), which is cumbersome.
So to get the answer to your problem, better describe the problem itself instead.

how to count elements after making a left join with doctrine

i have 2 tables: "User" and "States". What i pretend to do, is to count how many users are from certain state, ie:
state total users
santa fe 5
buenos aires 20
and so on.
I'm using codeigniter with doctrine, here's my code:
public function countByState(){
$this->qb = $this->em->createQueryBuilder();
$this->qb->select('s.state_id', $this->qb->expr()->count('u.state'))
->from('models\States', 's')
->leftJoin('s.state_id' , 'u')
->leftJoin('models\User', 'u')
->groupBy('s.state_id');
$query = $this->qb->getQuery();
$obj = $query->getResult();
return $obj;
}
and this is the error:
Fatal error: Uncaught exception 'Doctrine\ORM\Query\QueryException' with message '[Semantical Error] line 0, col 76 near 'u LEFT JOIN models\User': Error: Class models\States has no association named state_id' in C:\Desarrollo\new_frame_doctrine\site\application\libraries\data\Doctrine\ORM\Query\QueryException.php on line 47
Please use this sql query
SELECT s.name,count(*) FROM `users` u left join `state` s on u.stateid=s.id
group by s.id;
In the code please change accordingly!!
I tried this by creating two tables named state (with fields id and name)
and users(with fields id, name and state_id), It worked fine for me.
Cheers!!!

Resources