Hibernate Dynamic Order - hql

Hi i want to sort in HQL
ORDER BY IF g.groupAdminId=:adminid THEN 1 ELSE 0 END ASC
But it doesn't work, i want to have all entities where the user is admin first, how can i archieve this?

I don't believe it is possible to put named parameters outside a where clause.
It is possible to order according to expressions:
from User U
order by case
when U.group.name = 'Admin' then 0
when U.group.name = 'Superuser' then 1
else 2
end asc
More on case in HQL docs :
For your particular problem (having admins before other users) I suggest making two queries and combining the two lists in Java.
There are other ways around this but I do not like any of them:
Multiple mappings
Custom functions

Related

Laravel Eloquent Conditional inside Query like PLSQL

I'm trying to do conditional statement inside Laravel query, is it possible?
In PLSQL I would do the following to do IF ELSE, can I do it in Laravel Eloquent ?
select *
from x
where x.id = 1
and ( (varName = 'all') OR (x.name = 'red') )
What's happening up there is user is picking from a drop downbox (varName), and is either picking all colors as 'all', or picking individual colors.
I know it would be easy to write two IF Else statements and duplicate the SQL with each condition, but I have a really big SQL, and don't want to duplicate the whole SQL twice just for something simple. Is it possible to do this in Laravel? Or are there other ways to achieve it?
You may use whereRaw for this, for example
...
->where('x.id','=',1)
->whereRaw('(varName = "all" or x.name="red")')
...
Please note that the raw query isn't escaped by default, so make sure to do this if your handling user input.

How can I divide two HQL Count Results?

I want to compute the percentage of people who are not active divided by the percentage of people being active.
I will do something like the following HQL query but it did not work:
(select count(x) from People as x where x.active=false) /
(select count(x) from People as x where x.active=true)
How can I do that?
You can use a group by clause to express this. Here's how you could do it in Grails:
def countByAction = People.
executeQuery("select active, count(*) from People group by active")*.
toList().
collectEntries{it}
println (countByAction[true])
println (countByAction[false])
Since you are using HQL expression, I'm assuming you are using Hibernate. In this case I would recommend you using #Formula annotation. You may find additional information here:
Hibernate documentation - search for #Formula
Example of using #Formula annotation
Something like this should work
String hql = "select count(x)/(select count(x) from People as x where x.active=true)
from People as x where x.active=false";
Long result = (Long) em.createQuery(hql).getSingleResult();
NOTE: above is untested
I use countBy* Dynamic method that uses the properties of the domain class to query for the count of the number of matching records. see http://grails.org/doc/latest/ref/Domain%20Classes/countBy.html

hibernate - using 'having' without group by clause in hql

im trying to run an hql query which aggragets (sum) number of transactions made on a specific account, i dont need a group by since my where clause has a specific account filter (where account = :account)
i do, however, want to return the aggregated value only if it is smaller/bigger than some given value.
when im adding 'having' after the where clause without 'group by' im getting an error -
unexpected token: having
in native sql i succeeded adding 'having' without group by
any ideas on how to make it work with hql?
thanks alot
The reason why databases don't let you mix grouped columns with non-grouped and non-aggregated ones is, that for non-grouped/non-aggregated columns it would have to choose one row's value per group, but doesn't know how to pick one.
If you don't care, then you could just leave it away and if it doesn't matter because they're all the same, you could group by them, too.
It is not hql, but if you have native query, then run it like:
Query query = session.createSQLQuery("select, *** ,... blah blah")
//set If you need
query.setParameter("myparam", "val");
List result = query.list();
In my eyes this is nonsense. 'having' is done for conditions on a 'group by' result. If you don't group, then it does not make much sense.
I would say HQL can't do it. Probably the Hibernate programmers didn't think of this case because they considered it as not important.
And anyway, you don't need it.
If it is a simple query, then you can decide in your java code if you want the result or if you don't need it.
If it is in a subselect, then you can solve the problem with a where condition in the main select.
If you think it is really necessary then your invited to give a more concrete example.

Ruby on Rails: Search one table where multiple rows must be present in another table

I'm trying to create a search where a single record must have multiple records in another table (linked by id's and has_many statements) in order to be included as a result.
I have tables users, skill_lists, skill_maps.
users are mapped to individual skills through single entries in the skill_maps table. Many user can share a single skill and single user can have many skills trough multiple entries in the skill_maps table.
e.g.
User_id | Skill_list_id
2 | 9
2 | 15
3 | 9
user 2 has skills 9 and 15
user 3 has only skill 9
I'm trying to create a search that returns a hash of all users which have a set of skills. The set of required skill_ids appear as an array in the params.
Here's the code that I'm using:
skill_selection_user_ids = SkillMap.find_all_by_skill_list_id(params[:skill_ids]).map(&:user_id)
#results = User.find(:all, :conditions => {:id => skill_selection_user_ids})
The problem is that this returns all users that have ANY of these skills not users that have ALL of them.
Also, my users table is linked to the skill_lists table :through => :skill_maps and visa versa so that i can call #user.skill_list etc...
I'm sure this is a real newbie question, I'm totally new to rails (and programming). I searched and searched for a solution but couldn't find anything. I don't really know how to explain the problem in a single search term.
I personally don't know how to do this using ActiveRecord's query interface. The easiest thing to do would be to retrieve lists of users who have each individual skill, and then take the intersection of those lists, perhaps using Set:
require 'set'
skills = [5, 10, 19] # for example
user_ids = skills.map { |s| Set.new(SkillMap.find_all_by_skill_list_id(s).map(&:user_id)) }.reduce(:&)
users = User.where(:id => user_ids.to_a)
For (likely) higher performance, you could "roll your own" SQL and let the DB engine do the work. I may be able to come up with some SQL for you, if you need high performance here. (Or if anyone else can, please edit this answer!)
By the way, you should probably put an index on skill_maps.skill_list_id to ensure good performance even if the skill_maps table gets very large. See the ActiveMigration documentation: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
You'll probably have to use some custom SQL to get the user IDs. I tested this query on a similar HABTM relationship and it seems to work:
SELECT DISTINCT(user_id) FROM skill_maps AS t1 WHERE (SELECT COUNT(skill_list_id) FROM skill_maps AS t2 WHERE t2.user_id = t1.user_id AND t2.skill_list_id IN (1,2,3)) = 3
The trick is in the subquery. For each row in the outer query, it finds a count of records for that row that match any of the skills that you're interested in. Then it checks whether that count matches the total number of skills you're interested in. If there's a match, then the user must possess all of the skills you searched for.
You could execute this in Rails using find_by_sql:
sql = 'SELECT DISTINCT(user_id) FROM skill_maps AS t1 WHERE (SELECT COUNT(skill_list_id) FROM skill_maps AS t2 WHERE t2.user_id = t1.user_id AND t2.skill_list_id IN (?)) = ?'
skill_ids = params[:skill_ids]
user_ids = SkillMap.find_by_sql([sql, skill_ids, skill_ids.size])
Sorry if the table and column names aren't exactly right, but hopefully this is in the ballpark.

Linq-to-sql Not Contains or Not in?

I'm building a poll widget. I've 2 tables, call them Polls and PollsCompleted. I need to do a linq query to get all the Polls that do not exist for a given user in PollsCompleted.
I have the following sets:
For Polls
Where Active == True
For PollsCompleted
Where UserId == ThisUserId
Where PollId = Polls.Id
Now I need to get all Polls that do not exist in PollsCompleted. I need an example for this using either a single or multiple queries. I've tried to break it down into 2 queries.
Basically, I've 2 IQueryables of type T and T1. I want to take all T's where T.ID does not exist in T1.ParentId.
T.Where(x => ! T1.Select(y => y.ParentID).Contains(x.ID))
In Linq you often work from the bottom up. Here we first get a collection of all the parentIDs in T1 -- the T1.Select(...) part. Then we create a where clause that selects all of the Ts whose IDs are not contained in that set.
Note that the result is a query. To materialize it, use ToList() or similar on the statement above.
Use Except. That will work in this case.
For your reference Enumerable.Except Method

Resources