NHibernate Criteria Query - Select Distinct - nhibernate

I have a Person entity belongs to a person has a Country, I want to select all the distinct countries that have people in them. Easy in HQL
select distinct p.Country from Person p
How can I do this using a Criteria Query?

criteria.SetProjection(Projections.Distinct(Projections.Property("Country")));

Related

Could this be re-written without the union operator?

Consider this DB at https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
The goal is to write a query to list all the cities in that DB.
Can the query below be re-written without using the union operator? in ANSI SQL or any other ones. I just want to get a general idea. Thank you
SELECT City, country FROM Customers
UNION
SELECT City, country FROM Suppliers
order by city, country
The only other way (I can think of) to do it is with a FULL OUTER JOIN:
SELECT DISTINCT
COALESCE(c.City, s.City) AS City,
COALESCE(c.country, s.country) AS country
FROM Customers c FULL JOIN Suppliers s
ON s.City = c.City AND s.country = c.country
Note that UNION is the correct method for this requirement and that FULL OUTER JOIN is not supported by databases like MySql and SQLite.

SQL: Find all rows in a table when the rows are a foreign key in another table

The caveat here is I must complete this with only the following tools:
The basic SQL construct: SELECT FROM .. AS WHERE... Distinct is ok.
Set operators: UNION, INTERSECT, EXCEPT
Create temporary relations: CREATE VIEW... AS ...
Arithmetic operators like <, >, <=, == etc.
Subquery can be used only in the context of NOT IN or a subtraction operation. I.e. (select ... from... where not in (select...)
I can NOT use any join, limit, max, min, count, sum, having, group by, not exists, any exists, count, aggregate functions or anything else not listed in 1-5 above.
Schema:
People (id, name, age, address)
Courses (cid, name, department)
Grades (pid, cid, grade)
I satisfied the query but I used not exists (which I can't use). The sql below shows only people who took every class in the Courses table:
select People.name from People
where not exists
(select Courses.cid from Courses
where not exists
(select grades.cid from grades
where grades.cid = courses.cid and grades.pid = people.id))
Is there way to solve this by using not in or some other method that I am allowed to use? I've struggled with this for hours. If anyone can help with this goofy obstacle, I'll gladly upvote your answer and select your answer.
As Nick.McDermaid said you can use except to identify students that are missing classes and not in to exclude them.
1 Get the complete list with a cartesian product of people x courses. This is what grades would look like if every student has taken every course.
create view complete_view as
select people.id as pid, courses.id as cid
from people, courses
2 Use except to identify students that are missing at least one class
create view missing_view as select distinct pid from (
select pid, cid from complete_view
except
select pid, cid from grades
) t
3 Use not in to select students that aren't missing any classes
select * from people where id not in (select pid from missing_view)
As Nick suggests, you can use EXCEPT in this case. Here is the sample:
select People.name from People
EXCEPT
select People.name from People AS p
join Grades AS g on g.pid = p.id
join Courses as c on c.cid = g.cid
you can turn the first not exists into not in using a constant value.
select *
from People a
where 1 not in (
select 1
from courses b
...

Combining distinct and count() from two tables

I have two tables:
Customers (name, address, postcode (FK))
Postcodes (postcode (PK), county)
I want to find out how many customers are in each county.
I am assuming I need an inner join on postcode but don't know how to combine this with a count(customer_id) and distinct(county).
Although you can write queries with SELECT DISTINCT country it prevents you from doing aggregates such as COUNT. Instead you can use GROUP BY which broadly has the same effect as DISTINCT but with much more power and flexibility.
These two queries give the same results, but the second lets you then go on to add your JOIN and COUNT statements.
SELECT DISTINCT county FROM postcodes
SELECT county FROM postcodes GROUP BY county
By and large, don't use SELECT DISTINCT, but use this kind of pattern...
SELECT
postcodes.county,
COUNT(customers.customer_id)
FROM
postcodes
INNER JOIN
customers
ON customers.postcode = postcodes.postcode
GROUP BY
postcodes.county
Just join the Customers table to the Postcodes table on the common field 'postcode '. Then you can use Group By to get your counts and return one row per County
SELECT
County,
COUNT(Customer_Id) CustomerCount
FROM
Postcodes pc
JOIN Customers c ON pc.PostalCode = c.PostalCode
GROUP BY
County

Correct way to use "NOT IN" Postgres

I have two tables, People, and Vehicles. Vehicles belongs to people. Im trying to check if a person does not have a vehicle. I was attempting to do this by joining People and Vehicles, and displaying the persons ID that is NOT IN Vehicles.person_id.
This is returning nothing, and has me wondering if there is something I did wrong, or if there is a more efficient way of doing this.
Query is below
Select People.id
From People
INNER JOIN Vehicles
on People.id=Vehicles.person_id
where People.id NOT IN Vehicles.person_id;
Use left join to figure out the persons with no vehicles
Select distinct People.id
From People
LEFT JOIN Vehicles on People.id=Vehicles.person_id
where Vehicles.person_id is NULL
NOT IN can have issues with NULL values, and should probably be avoided for performance reasons if the subquery is very large.
Try NOT EXISTS:
SELECT p.id
FROM People p
WHERE NOT EXISTS (
SELECT 1
FROM Vehicles v
WHERE v.person_id = p.id)
another solution, using sets:
Select id From People
except
SELECT person_id FROM Vehicles
Use Subquery as below:
Select id
From People
WHERE id NOT IN (SELECT distinct person_id
FROM Vehicles
WHERE person_id IS NOT NULL)
select all people who are not in (by Select id From People WHERE id NOT IN) the List of all the people who has vehicle by SELECT distinct person_id FROM Vehicles (you could avoid null as well here if you want).

NHibernate Criteria Query - Select Distinct with Joined Entity

I have a Person entity. Every person has a country, I want to select all the distinct countries that have people in them. This Criteria Query returns all the distinct CountryID's
criteria.SetProjection(Projections.Distinct(Projections.Property("Country")));
How do I alter it to join and fetch the Country entity, not just the ID?
Any easy way would be to use a subquery. That is, you could select the whole country on the outer query where the country ID matches the inner query.
Subqueries.PropertyIn(
"Country",
innerDetachedCriteriaWhichFindsCountriesWithPeopleAndProjectsCountryId)