Complex "Order By" using Specification API Hibernate - postgresql

Is there any way i can do this select query using Hibernate Specification API (criteria API)?
select * from employee order by (CASE
WHEN full_name IS NOT NULL
AND full_name <> '' THEN full_name
WHEN CONCAT(first_name, last_name) IS NOT NULL
AND CONCAT(first_name, last_name) <> '' THEN CONCAT(first_name, ' ', last_name)
END) nulls first
My specification method:
Specification { root: Root<Employee>, criteriaQuery: CriteriaQuery<*>, cb: CriteriaBuilder ->
...
criteriaQuery.orderBy(
cb.asc(
//TODO something?
)
)
...
}

Try this :
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Route> query = criteriaBuilder.createQuery(Employee.class);
List<Order> orders = new ArrayList();
Root<Employee> employeeRoot = query.from(Employee.class);
orders.add(criteriaBuilder.desc(employeeRoot .get("firstName")));
orders.add(criteriaBuilder.desc(employeeRoot .get("lastName")));
query.orderBy(orders);

Related

EF Core Filtered Include with Select

Sorry for my English.
I ran into a mistake with EF Core 5.0.9 when is use Filtered Include and Select in same time and i don't know is a bug or feature. :)
return await _dbContext.User
.Where(u => !u.TOROLT)
.Where(u => ids.Contains(u.Id))
.Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.Select(u => new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = u.EventUsers.First().Id,
IsCelebrated = u.EventUsers.First().IsCelebrated,
IsEventAdmin = u.EventUsers.First().IsEventAdmin,
IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
IsInvited = u.EventUsers.First().IsInvited,
})
.ToListAsync();
In this time the first elements is select is not from filtered include just from a normal include. SQL Script from Profiler:
SELECT
[u].[Id],
[u].[FirstName],
[u].[LastName],
(
SELECT TOP(1) [e].[Id]
FROM [dbo].[EventUser] AS [e]
WHERE [u].[Id] = [e].[UserId]) AS [EventUserId],
(
SELECT TOP(1) [e0].[IsCelebrated]
FROM [dbo].[EventUser] AS [e0]
WHERE [u].[Id] = [e0].[UserId]) AS [IsCelebrated],
(
SELECT TOP(1) [e1].[IsEventAdmin]
FROM [dbo].[EventUser] AS [e1]
WHERE [u].[Id] = [e1].[UserId]) AS [IsEventAdmin],
(
SELECT TOP(1) [e2].[IsInviteAccepted]
FROM [dbo].[EventUser] AS [e2]
WHERE [u].[Id] = [e2].[UserId]) AS [IsInviteAccepted],
(
SELECT TOP(1) [e3].[IsInvited]
FROM [dbo].[EventUser] AS [e3]
WHERE [u].[Id] = [e3].[UserId]) AS [IsInvited]
FROM [dbo].[User] AS [u]
WHERE ([u].[TOROLT] <> CAST(1 AS bit))
AND [u].[Id] IN (2, 1, 3, 4, 5)
But if is separate filtered include and select, than it work's fine, but this select complete record and not the part of him from database:
var a = await _dbContext.User
.Where(u => !u.TOROLT)
.Where(u => ids.Contains(u.Id))
.Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.ToListAsync();
return a.Select(u => new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = u.EventUsers.First().Id,
IsCelebrated = u.EventUsers.First().IsCelebrated,
IsEventAdmin = u.EventUsers.First().IsEventAdmin,
IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
IsInvited = u.EventUsers.First().IsInvited,
})
.ToList();
Any idea why is this, and how can i solve solve this?
THX
Include is completely ignored if you have custom projection Select, so your filter will be also ignored. It is not a bug, Include works only when you get whole entity from query.
Anyway consider to rewrite your query:
var query =
from u in _dbContext.User
where !u.TOROLT && ids.Contains(u.Id)
from eu in u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId)
.Take(1)
.DefaultIfEmpty()
select new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = eu.Id,
IsCelebrated = eu.IsCelebrated,
IsEventAdmin = eu.IsEventAdmin,
IsInviteAccepted = eu.IsInviteAccepted,
IsInvited = eu.IsInvited,
};
var result = await query.ToListAsync();

How how do I write a knex migration file to automatically update existing Database

I want to create a migration file for the following query
`insert into table1(column1)
select o.name from original_table as o`
`update original_table as o
set new_column = (select t1.id from table1 as t1
where t.column1 = o.old_column)`
So far I came up with this. The first part works but I am stuck with the second part
`exports.up = function (knex, Promise) {
return Promise.resolve()
.then(() => knex('original_table').select('old_column'))
.then((rows) => knex('table1').insert(rows))
.then(() => knex('table1 as t').select(['t.column1',
'column2']).join('original_table
as o', 'o.old_column', 't.column2'))
.then((rows) => knex('original_tableas
o').whereIn('original_table.old_column', rows.column2).update('column2',
rows.column1))
};
exports.down = function (knex) {
return Promise.resolve()
.then(() => console.log("Deletes updated records"));
};`
Thank you in advance.
First query is actually pretty inconvenient to form with knex, but knex.raw can do pretty much anything. Following would be the most knexy way I can think of to write it:
exports.up = async (knex) => {
// insert into table1(column1) select o.name from original_table as o
await knex.raw('insert into ?? (??) ??', ['table1', 'column1', knex('original_table').select('name')]);
// update original_table as o set
// new_column = (
// select t1.id from table1 as t1 where t1.column = o.old_column
// )
await knex('original_table as o').update({
new_column: knex('table1 as t1').select('id').where('t1.column', 'o.old_column')
});
}

Eloquent sort table before join

I have this Eloquent query:
User::select([
'users.name AS name',
'order.name AS name'
])
->leftJoin( 'orders', 'users.id', '=', 'users.order_id')
->get()->toArray();
I need to sort orders table by id before passing it to leftJoin

Add conditional statement in PostgreSQL query

I have this query:
WITH grouped_messages AS
(SELECT
um.conversation_id,
array_agg(json_build_object('message', um.message, 'sent_at', um.created_at))
FROM user_messages um
INNER JOIN users_conversations c ON c.conversation_id = um.conversation_id
WHERE c.user_id = '#{user_id}' AND um.user_id != '#{user_id}' #{ "and um.created_at >= '#{timestamp}'" IF TIMESTAMP}
GROUP BY um.conversation_id
),
senders AS
(SELECT
gm.conversation_id,
json_build_object('id', u.id, 'user_name', u.user_name, 'avatar',
('https://my-staging.s3.amazonaws.com/public/uploads/user/' || u.id :: TEXT ||
'/avatar.jpg')) AS sender
FROM grouped_messages AS gm
INNER JOIN users_conversations c ON c.conversation_id = gm.conversation_id
INNER JOIN users u ON u.id = c.user_id
WHERE u.id != '#{user_id}'
)
SELECT json_object_agg(grouped_messages.conversation_id,
json_build_object('new_messages', grouped_messages.array_agg, 'sender', senders.sender))
FROM grouped_messages
INNER JOIN senders ON senders.conversation_id = grouped_messages.conversation_id
Which outputs, for example:
{
"62": {
"new_messages": [
{
"message": "some",
"sent_at": "2016-05-30T20:19:53.786024"
},
{
"message": null,
"sent_at": "2016-05-30T20:19:26.408814"
}
],
"sender": {
"id": "e4ba308b-a5cf-47ad-b8d6-d774eb325411",
"user_name": null,
"avatar": "https://my-staging.s3.amazonaws.com/public/uploads/user/e4ba308b-a5cf-47ad-b8d6-d774eb325411/avatar.jpg"
}
}
}
Now, what I need is to have a conditional statement in this query.
If u (user) avatar is not NULL then apply this 'https://my-staging.s3.amazonaws.com/public/uploads/user/' || u.id::text || '/avatar.jpg', otherwise just insert ':null' string (so that any JSON parser recognizes it as a null object).
Not sure how to put this if-else here in select statement and also how to ensure that part about JSON parser.
worked for me:
(SELECT gm.conversation_id, json_build_object('id', u.id, 'user_name', u.user_name,
'avatar', (
CASE WHEN u.avatar IS NULL THEN ':null'
ELSE ('https://my-staging.s3.amazonaws.com/public/uploads/user/' || u.id::text || '/avatar.jpg')
END))
You can provide case-statement in SELECT block as if it were value (with optional AS).
This is a good use of the CASE expression. In this scenario, you want to return either a hard URL to their avatar if the avatar field is not null, and NULL otherwise.
This is accomplished thus (omitting the other portions of the query for readability):
json_build_object('id', u.id, 'user_name', u.user_name,
'avatar',
CASE WHEN u.avatar IS NULL
THEN NULL
ELSE
(
'https://my-staging.s3.amazonaws.com/public/uploads/user/'
|| u.id :: TEXT ||
'/avatar.jpg') END) AS sender

zend framework subquery

I am using zend framework 1.12. I have following query to run.
"SELECT name,(select count(*) from org_quote_template_items where org_quote_template_items.quote_template_id = org_quote_templates.`id` ) as total_line_item FROM `org_quote_templates`"
In my model file , I created it like this. following is my model file.
class default_Model_DbTable_QuoteTemplates extends Zend_Db_Table_Abstract
{
/**
* Name of the original db table
*
* #var string
*/
protected $_name = 'org_quote_templates';
public function getAllTemplate($where){
$select = $this->select();
$subquery = " (SELECT COUNT(*) FROM org_quote_template_items WHERE org_quote_template_items.quote_template_id = org_quote_templates.`id` )";
$select->from(array($this), array('org_quote_templates.*','total_line_items' => new Zend_Db_Expr($subquery)));
$select = $select->where('organization_id = ?',$where['org_id']);
$adapter = new Zend_Paginator_Adapter_DbSelect($select);
$paginator = new Zend_Paginator($adapter);
$paginator->setItemCountPerPage(
Zend_Registry::get('config')->paginator->general);
pr($adapter);
exit;
}
}
I am getting following error when I run the code.
" exception 'Zend_Db_Table_Select_Exception' with message 'Select query cannot join with another table' "
please let me know what should I do ?
There is an error in your request. You should have:
$select = $this->select ();
$subquery = "(SELECT COUNT(*) FROM dtempls WHERE order_id = orders.id)";
$select->from ($this, array (
'id',
'total_line_items' => new Zend_Db_Expr ($subquery)
));
I think you have to use setIntegrityCheck(false) for accomplishing that. Check this link
You can try this way in zend
$this->select()
->setIntegrityCheck(false)
->from(array('oqt' => 'org_quote_templates'),array('total_line_item'))
->joinLeft(array('oqti' => 'org_quote_template_items'), 'oqti.quote_template_id = oqt.id', array(count(*) as count))