I'm trying to express a SQL query using NHibernate's Criteria API, and I'm running into difficulty because I'm thinking in a database-centric way while NHibernate is object-centric.
SQL (works great):
select outerT.id, outerT.col1, outerT.col2, outerT.col3
from tbl outerT
inner join
(select max(innerT.id)
from tbl innerT
group by innerT.col1) grpT
on outerT.id = grpT.id
Essentially, this is a self-join of a table against a subset of itself. I suppose I could try turning the self-join into a restriction:
select outerT.id, outerT.col1, outerT.col2, outerT.col3
from tbl outerT
where outerT.id in (select max(innerT.id) from tbl innerT group by innerT.col1)
But I'm not sure how to express that using NHibernate either; I'm fighting with the DetachedCriteria's ProjectionList and wanting to select only max(id) while grouping by col1.
Thanks so much for your suggestions!
I don't know if I should post this as a new answer or to add it as a comment on the original question, but I think I've resolved a similar problem in this thread:
Selecting on Sub Queries in NHibernate with Critieria API
AFAIK you cannot join to subqueries at all in NHibernate but you can re-organise the query to use either an EXISTS or IN clause to replicate the same functionality.
I realise the question asks for this to be done using the Criteria API but I thought I would post a HQL version which may give someone else some ideas.
var results = session.CreateQuery("from Product p where p.Id in (
select max(p2.id)
from Product p2
group by p2.col1
)")
I also found this JIRA issue surrounding the Criteria API and not including group by columns in the select. Currently it looks like what you want cannot be achieved using the Criteria API at all.
Group By Property without adding it to the select clause
UPDATE
Using the example from Monkey Coders post looks like you can do this:
var subquery = DetachedCriteria.For<Product>("p")
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("p.Col1"))
.Add(Restrictions.EqProperty("p2.Id", Projections.Max("p.Id"));
var query = DetachedCriteria.For<Product>("p2")
.Add(Subqueries.Exists(subquery));
Which would produce the following SQL
select *
from Product p2
where exists (
select p.col1
from Product p
group by p.col1
having p2.Id=max(p.Id)
)
Related
I want to do self-join I have written a code as well but its throwing an error and it seems that there is some issue with an alias.
Apart from this it would also be helpful for me if someone let me know any best site where I can learn query in MS Access. I searched a number of places everywhere, it is showing through UI Interface but I want to learn query in MS Access.
(SELECT distinct itemname,vendorname,price,count(*)
from vendor_Details1
group by itemname,vendorname,price
order by vendorname) A
inner join
(SELECT distinct itemname,vendorname,price,count(*)
from vendor_Details1
group by itemname,vendorname,price
order by vendorname) B
on A.vendorname=B.vendorname
It is entirely unclear what you are trying to do. However, "join" is an operator in the FROM clause that operates on two tables, views, or subqueries.
The structure of a self-join looks like:
select . . . -- list of columns here
from t as t1 inner join -- you need aliases for the table so you can distinguish the references
t as t2
on t1.? = t2.? -- the join condition goes here
Your query doesn't even have a select.
I am using JPA and Hibernate, but my need is too complicated to build a HQL, at least for me.
I decided to use native SQL.
I need to get some records/entities with their child lists but, i need to filter childs, i do not want all the childs.
Is this possible?
For example i have three tables like
conversation_table:
id
mail_table:
id, conversation_id, sender_id
user_table:
id, married_bool
I need conversation entities having lists that filled by mails those are send by married users.
I tried so far
Select * from conversation_table join mail_table on ( mail_table.sender_id=user_table.id and user_table.married_bool=true)
I am getting an error like:
user_table is unknown
I tried
Select * from (conversation_table, user_table, mail_table) join mail_table on ( mail_table.sender_id=user_table.id and user_table.married_bool=true)
I am getting
mail_table is non unique table/alias
This is only a light example, also need to fill some entity lists of mail entity in other tables for example recipient_table, i think i have to add join clauses for filling these too in native query, am i right? Also i am getting 'not known'/'non unique alias' errors, when try this additional join clauses.
Thanks for suggestions.
Something like this:
SELECT *
FROM conversation_table CT
JOIN mail_table MT
ON CT.Id = MT.conversation_id
JOIN user_id UI
ON MT.sender_id=UI.id
WHERE UT.married_bool = 1
If you really want to use Hibernate ORM for this query they Criteria Query is the best approach for this. Recently, i have the same requirement and have used Criteria only.
I am new to SQL, so this is probably very simple, however, I wasn't able to find the solution.
Basically my query is as follows:
SELECT UserID
FROM Users
NOT UNION
SELECT UserID
FROM User_Groups
WHERE GroupID = '$_[0]'
However, I am not sure what the syntax is to exclude one query from another.
What I am trying to say is give me all the user ID's except for those that are in group X.
SELECT UserID FROM Users
WHERE UserID NOT IN (SELECT UserID FROM User_Groups WHERE GroupID = ?)
P.S. Don't interpolate variables into your queries as this can lead to SQL injection vulnerabilities in your code. Use placeholders instead.
SELECT Users.UserID
FROM Users
LEFT JOIN User_Groups ON Users.UserID = User_Groups.UserID
WHERE Users.GroupID = '$_[0]'
AND User_Groups.UserID IS NULL
You can left join to the other table and then put an IS NULL check on the other table in you WHERE clause as I've shown.
You could use EXCEPT as well:
SELECT UserID
FROM Users
EXCEPT
SELECT UserID
FROM User_Groups
WHERE GroupID = '$_[0]'
EXCEPT is SQL's version of set subtraction. Which of the various approaches (EXCEPT, NOT IN, ...) you should use depends, as usual, on your specific circumstances, what your database supports, and which one works best for you.
And eugene y has already mentioned the SQL injection issue with your code so I'll just consider that covered.
I linked to the PostgreSQL documentation even though this isn't a PostgreSQL question because the PostgreSQL documentation is quite good. SQLite does support EXCEPT:
The EXCEPT operator returns the subset of rows returned by the left SELECT that are not also returned by the right-hand SELECT. Duplicate rows are removed from the results of INTERSECT and EXCEPT operators before the result set is returned.
NOT IN() - Negating IN()
SELECT UserID FROM User_Groups WHERE GroupID NOT IN('1','2')
The IN() parameter can also be a sub-query.
Are you looking for a solution to be used with a postgres or a mySQL database?
Or are you looking for a plain SQL solution?
With postgres a subquery with "WHERE NOT EXISTS" might work like:
SELECT * FROM
(SELECT * FROM SCHEMA_NAME.TABLE_NAME)
WHERE
(NOT EXISTS (SELECT * FROM SCHEMA_NAME.TABLE_NAME)
I have a data model in django called MainData which was created on top of a table called "my_data".
I want to perfom a simple calculation on top of this table via django API. The query is as follow:
select main.id,
sum(main.num - secondary.num) as result
from (select * from my_data
where some_value > 10) as main,
my_data as secondary
where
main.id != secondary.id and
main.a > secondary.a
group by main.id
The MainData model has all the relevant fields (num, id, a and some_value).
How can I implement this query via django? (I'm trying to avoid using direct SQL)
Thanks for the help
Try this question, it seems similar:
Django equivalent for count and group by
That's a tough one. Django doesn't really provide an easy way to join a table with itself without resorting to SQL. Here's the best I can come up with without using SQL. The results returned in the results variable are equivalent to those you would get with the SQL query you provided; however, the execution is somewhat less efficient.
from django.db.models import Sum, Count
from your_app.models import MyData
results = []
for m in MyData.objects.filter(some_value__gt=10):
result = MyData.objects.filter(a__lt=m.a).aggregate(
count=Count('num'), sum=Sum('num'))
if result['count']:
results.append({
'id': m.id,
'result': result['count'] * m.num - result['sum']})
print results
You should also have a look at the extra() and raw() methods Django provides for QuerySets, which would allow you to make complex queries such as yours efficiently while still keeping things Djangoesque.
I have an NHibernate query that looks like this:
var query = Session.CreateQuery(#"
select o
from Order o
left join o.Products p
where
(o.CompanyId = :companyId) AND
(p.Status = :processing)
order by o.UpdatedOn desc")
.SetParameter("companyId", companyId)
.SetParameter("processing", Status.Processing)
.SetResultTransformer(Transformers.DistinctRootEntity);
var data = query.List<Order>();
I want to implement paging for this query, so I only return x rows instead of the entire result set.
I know about SetMaxResults() and SetFirstResult(), but because of the left join and DistinctRootEntity, that could return less than x Orders.
I tried "select distinct o" as well, but the sql that is generated for that (using the sqlserver 2008 dialect) seems to ignore the distinct for pages after the first one (I think this is the problem).
What is the best way to accomplish this?
In these cases, it's best to do it in two queries instead of one:
Load a page of orders, without joins
Load those orders with their products, using the in operator
There's a slightly more complex example at http://ayende.com/Blog/archive/2010/01/16/eagerly-loading-entity-associations-efficiently-with-nhibernate.aspx
Use SetResultTransformer(Transformers.AliasToBean()) and get the data that is not the entity.
The other solution is that you change the query.
As I see you're returning Orders that have products which are processing.
So you could use exists statement. Check nhibernate manual at 13.11. Subqueries.