NHibernate Criteria Subquery help - nhibernate

I am using NHibernate and I my requirement is that I have 2 tables, User and Ticket. I want all the records that are in User but not in Ticket. The Ticket table has UserId as reference key to the Primary key ID of User table. Below is my code,
RegNotTickTemplate.Criteria = DetachedCriteria.For(typeof(User));
RegNotTickTemplate.Criteria.Add(Subqueries.PropertyNotIn("ID",DetachedCriteria.For(typeof(Ticket))
.SetProjection(Projections.Property("UserID"))));
The above query doesnt return correct set of records.

As an alternative, you could try using HQL. I never use Criteria as I find HQL more readable (it is almost the same as SQL except you get to query based on the entities rather than the tables).
Chapter 13. HQL: The Hibernate Query Language
IQuery query = Session.CreateQuery(
"from User where Id not in (select UserId from Ticket)");
query.List<User>();
If that is still no good, you can always do an SQL query
ISQLQuery query = Session.CreateSQLQuery(sql);

What you are missing is: the count of tickets for this user should be greater than zero. Here is how you can implement it:
RegNotTickTemplate.Criteria = DetachedCriteria.For(typeof(User));
RegNotTickTemplate.Criteria.Add(Subqueries.PropertyIn("Id",
DetachedCriteria.For<Ticket>()
.SetProjection(Projections.GroupProperty("User"))
.Add(Restrictions.Eq(Projections.RowCount(), 0))));
If you don't want the count of rows you can do the following:
RegNotTickTemplate.Criteria = DetachedCriteria.For(typeof(User),"user");
RegNotTickTemplate.Criteria.Add(Subqueries.Exists(DetachedCriteria.For<Ticket>("ticket")
.SetProjection(Projections.Property("User"))
.Add(Restrictions.EqProperty("user.Id", "User"))));

Related

SQL Query concatenation flagged in SonarQube

I have a method where I get a sql query as parameter. This is used in an IN clause to form a bigger query to Select/Delete data. Something like this:
SQL = "SELECT ID FROM EMPLOYEE WHERE DEPARTMENT = 'HR'"
BIG_SQL = "DELETE FROM EMPLOYEE WHERE ID IN ("+SQL+")
It was flagged by SonarQube. Is there a better way to write the above code?
As I understand the purpose of the 2 queries is to delete rows from the table.
In the table EMPLOYEE the column ID is the primary key, right?
So you could just have a DELETE statement like this:
DELETE FROM EMPLOYEE WHERE DEPARTMENT = 'HR'
There is no need to get the ids by using the condition:
WHERE DEPARTMENT = 'HR'
and then use them to delete since this condition can be applied to directly delete the rows.

How can I convert a MVC sql query to a Linq query?

I am new in MVC. Linq is the system of making queries in database. but I am having difficulties right now with Linq. Anyone know how to convert my sql statement to Linq?
My entities, seperate context
localDB.summaries
accountDB.account
SELECT * FROM summary
WHERE studentID =
(SELECT studentID FROM accounts WHERE username = 'username123')
FROM user IN localDB.summaries
WHERE -------- please guide my linq--------
SELECT user
At a guess without knowing your entities:
var query = from user in localDB.summaries
join account in localDB.accounts on user.studentID equals account.studentID
where account.username == "username123"
select user;
I am assuming that accounts table has been mapped with student on the basis of student id I mean there is a foreign key relationship so by assuming that:
var data = localDB.summaries.where(c=>c.Students.Account.FirstorDefault().username == "username123")

Help with NHibernate query

I have 2 tables, Plan and Ticket. I want all the records that are in TravelPlan but not in Ticket.
Template.Criteria.CreateCriteria("Plan")
.Add(Subqueries.PropertyNotIn("UserID",
DetachedCriteria.For(typeof(Ticket))
.SetProjection(Projections.Property("UID"))));
The above query doesnt return any records..
I can't guess what SearchTemplate does, but you are applying the projection to the outer criteria instead of the detached one.
Also, the "root" criteria should be for TravelPlan, not Ticket.
In other words:
criteria = DetachedCriteria.For<TravelPlan>()
.Add(Subqueries.PropertyNotIn(
"UserId",
DetachedCriteria.For<Ticket>()
.SetProjection(Projections.Property("UID"))))
This assumes TravelPlan has a UserID property that is matches the UID property in Ticket.

What is the best way to reduce sql queries in my situation

Here is the situation,each page will show 30 topics,so I had execute 1 sql statements at least,besides,I also want to show how many relpies with each topic and who the author is,thus
I have to use 30 statements to count the number of replpies and use other 30 statements to find the author.Finally,I got 61 statements,I really worry about the efficiency.
My tables looks like this:
Topic Reply User
------- ---------- ------------
id id id
title topic_id username
... ...
author_id
You should look into joining tables during a query.
Joins in SQLServer http://msdn.microsoft.com/en-us/library/ms191517.aspx
Joins in MySQL http://dev.mysql.com/doc/refman/5.0/en/join.html
As an example, I could do the following:
SELECT reply.id, reply.authorid, reply.text, reply.topicid,
topic.title,
user.username
FROM reply
LEFT JOIN topic ON (topic.id = reply.topicid)
LEFT JOIN user ON (user.id = reply.authorid)
WHERE (reply.isactive = 1)
ORDER BY reply.postdate DESC
LIMIT 10
If I read your requirements correctly, you want the result of the following query:
SELECT Topic.title, User.username, COUNT(Reply.topic_id) Replies
FROM Topic, User, Reply
WHERE Topic.id = Reply.topic_id
AND Topic.author_id = User.id
GROUP BY Topic.title, User.username
When I was first starting out with database driven web applications I had similar problems. I then spent several years working in a database rich environment where I actually learned SQL. If you intend to continue developing web applications (which I find are very fun to create) it would be worth your time to pick up a book or checking out some how-to's on basic and advance SQL.
One thing to add, on top of JOINS
It may be that your groups of data do not match or relate, so JOINs won't work. Another way: you may have 2 main chunks of data that is awkward to join.
Stored procedures can return multiple result sets.
For example, for a summary page you could return one aggregate result set and another "last 20" result set in one SQL call. To JOIN the 2 is awkward because it doesn't "fit" together.
You certainly can use some "left joins" on this one, however since the output only changes if someone updates/adds to your tables you could try to cache it in a xml/text file. Another way could be to build in some redundancy by adding another row to the topic table that keeps the reply count, username etc... and update them only if changes occur...

Count the number of rows in each group

Using CodeIgniter's Active Record class and MySQL, I have a table of posts with user_id and various other fields, and I want to count how many posts each user has made. I could get rows where user_id = $whatever and count the number of results, but I'd have to loop through every user_id and use that count_all_results() query over and over for each one.
There must be a better way! If every field just had a field with a 1 in it, I could select_sum up that field and get a count. But that seems dumb.
Many thanks in advance!
Using active record should be:
$this->db->select('field1, ... ,fieldn, count(1) as number_elements_of_row');
$this->db->group_by(array('field_group_1', ... ,'field_group_n'));
$result = $this->db->get('mytable');
so $result will have what you need!