NHibernate + join to derived table - nhibernate

In a table that stores multiple rows per employee, I want to pull one row per employee that represents the most recent entry for each employee. Here's where I am with hand-written SQL:
SELECT [all the selected columns here]
FROM Nominations t
inner join
(select max(NominationId) mostRecentNominationId,
EmployeeId from Nominations group by EmployeeId) n
on n.mostRecentNominationId = t_.NominationId
From source data like this:
nomination_id employee_id
-------------------------------
1 5
2 5
4 10
7 10
That'll give me something like this:
nomination_id employee_id
-------------------------------
2 5
7 10
I haven't been able to figure out how to accomplish that type of query via NHibernate ICriteria. Any thoughts?

Here is what you need to do:
DetachedCriteria dCriteria = DetachedCriteria.For<Nomination>("nomination")
.SetProjection(Projections.Max("nomination.Id"))
.Add(Restrictions.EqProperty("nomination.EmployeeId", "employee.Id"));
var nominations = Session.CreateCriteria<Nomination>("nom")
.CreateCriteria("Employee", "employee")
.Add(Subqueries.PropertyEq("nom.Id", dCriteria)).List<Nomination>();
This is not equilevant to the SQL query providfed in the question but it does exactly the same thing.
The SQL query that is generated by the above criteria query is:
SELECT *
FROM Nomination nom
inner join Employee employee on nom.EmployeeId=employee.EmployeeId
WHERE nom.NominationId =
(SELECT max(nomination.NominationId) as maxID
FROM Nomination nomination
WHERE nomination.EmployeeId = employee.EmployeeId)

Related

How to Limit Results Per Match on a Left Join - SQL Server

I have a table with student info [STU] and a table with parent info [PAR]. I want to return an email address for each student, but just one. So I run this query:
SELECT [STU].[ID], [PAR].[EM]
FROM (SELECT [STU].* FROM DB1.STU)
STU LEFT JOIN (SELECT [PAR].* FROM DB1.PAR) PAR ON [STU].[ID] = [PAR].[ID]
This gives me the below table:
Student ID ParentEmail
1 jim#email.com
1 sarah#email.com
2 paul#email.com
2 tim#email.com
3 bill#email.com
3 frank#email.com
3 joyce#email.com
4 greg#email.com
5 tony#email.com
5 sam#email.com
Each student has multiple parent emails, but I only want one. In other words, I want the output to look like this:
Student ID ParentEmail
1 jim#email.com
2 paul#email.com
3 frank#email.com
4 greg#email.com
5 sam#email.com
I've tried so many things. I've tried using GROUP BY and MIN/MAX and I've tried complex CASE statements, and I've tried COALESCE but I just can't seem to figure it out.
I think OUTER APPLY is the simplest method:
SELECT [STU].[ID], [PAR].[EM]
FROM DB1.STU OUTER APPLY
(SELECT TOP (1) [PAR].*
FROM DB1.PAR
WHERE [STU].[ID] = [PAR].[ID]
) PAR;
Normally, there would be an ORDER BY in the subquery, to give you control over which email you want -- the longest, shortest, oldest, or whatever. Without an ORDER BY it returns just one email, which is what you are asking for.
If you just want one column from the parent table, a simple approach is a correlated subquery:
select
s.id student_id,
(select max(p.em) from db1.par p where p.id = s.id) parent_email
from db1.stu s
This gives you the greatest parent email per student.

How to get the unmatched records from two tables using Joins

I have two tables one is teacher and another is Department which is mentioned below.
Teacher Table
Id Name
1 xyz
2. Gjd
3. Dftr
4 dhdk
Department Table
Id Name EMPID
1 SQL. 2
2. PHP. 4
3. JAVA. 1
4 PEARL. 5
QUESTION
i want those records of teacher which are not link with any Department.
you can use following statement using left join then filter Teacher that not matched
SELECT t.*
FROM Teacher t
left join Department d on d.EMPID = t.Id
where d.id is null
SELECT * FROM teachers WHERE
id NOT IN (SELECT DISTINCT EMPID FROM departments) ;
Hope this helps.!!
you can do it by inner query..
select * from teacher where id not in (select empid from department);

SQL: Unable to find a join or union to produce the following table

A Pupil table with { ID, LastName}
a Subject Table with {ID, SubjectName}
and a Report Table with {ID, PupilID, SubjectID, Grade}
There is a one-to-many relationship between Pupil and Report Tables, and Subject and Report Tables.
I want to generate a table like this for say subjectID = 1
Pupil.ID Pupil.LastName SubjectID Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
The problem is that the Report table would contain just 2 entries for subject 1:
PupilID SubjectID Grade
----1------- 1 ----------- B
----4------- 1 ----------- A
Left joins don't seem to work since there are only 2 entries in the report table for subject 1
SAMPLE DATA
{Pupil Table}
ID LastName
1 ...Smith
2 ...Jones
3 ...Weston
4 ...Knightly
{Subject Table}
ID SubjectName
1 ....Maths
2 ....Physics
3 ....Chemistry
{Report Table}
ID PupilID SubjectID Grade
1 .......1 ..........1 ..........B
2 .......4 ..........1 ..........A
When I do a search on SubjectID = 1 I want the table:
Pupil.ID .......Pupil.LastName ........SubjectID ...........Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
Access doesn't do subqueries very easily, so everything gets crammed into the FROM clause with a series of wrapped parentheses. Based on your sample data and my fighting Access to stop being unnecessarily difficult, I came up with this:
SELECT ps.Pupil_ID, ps.LastName, ps.Subject_ID, r.Grade
FROM (SELECT * FROM (SELECT ID AS Pupil_ID, LastName FROM Pupil) p,
(SELECT DISTINCT ID AS Subject_ID FROM Subject)) ps
LEFT JOIN REPORT r ON r.PupilID = ps.Pupil_ID AND r.SubjectID = ps.Subject_ID
ORDER BY Pupil_ID, Subject_ID;
The subquery "ps" is a cartesian join of the Pupil and Subject table views that I specified. At this point, your query would look like this:
(LastName column not shown for clarity)
StudentID|SubjectID
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Now, using that Cartesian join subquery (pupilstudent -> ps), I use a LEFT JOIN to assign the Report table to each unique student's ID and subject ID. Therefore, if a student did not take a particular class, there will be a NULL value in the final result.
I tested this in Access using your sample data and it works on my machine.
Also as a note, it is poor practice to have a field called just ID in each table (e.g. in the Pupil table, ID becomes PupilID). This makes it much easier to use, and it self documents.
Cross join pupil and subject tables and left join result to report table
What you need is a cross join:
SELECT Pupil.ID, Pupil.LastName, SubjectID, Grade FROM
Pupil, Subject LEFT JOIN Report ON Subject.ID=Report.SubjectID
WHERE Subject.ID=1
To combine every pupil with every (or with a particular) subject, use cross join; Then use left join to get the corresponding grades:
select *
from pupil p cross join (select * from subject where id = 1) s
left join report on subjectId = s.id and pupilId = p.id

Returning DISTINCT rows in sql query

I have two tables. One is clients, that has a clientID and entity, the other is LogOnLink which has a clientID and LogonID. The LogOnLink table can the same clientID entered into it multiple times. So i'm trying to run a query where I do a search for an Entity Joining the LogonLink table. The problem i'm having is that if an entity is in the logonLink table 20 times, i get the name returned twenty times. How do i make it so that it only shows me one instance of an entity. Keep in mind that there can be similar entity names so If i have "Company 1" and "Company 2" in the db, i need to show both companies if someone types in companies. I tried doing DISTINCT but it doesn't distinct it by clientID in the LogOnLink table. Here's what i have so far.
SELECT DISTINCT ll.logonID, entity
FROM clients c
INNER JOIN LogOnsLink ll ON ll.clientID = c.clientID
WHERE c.entity LIKE '%Com%'
ORDER BY entity
Clients Table
------------------------------------
clientID entity
2 Company A
8 Company B
43 Company C
LogOnLinks Table
------------------------------------
LogonLinkID clientID LogonID
4 2 3
5 2 7
21 8 20
6 2 9
3 8 10
45 43 3
You'll need to perform some kind of aggregate on the data from LogOnsLink or you'll always get 20 rows...
Try this
SELECT entity, COUNT(ll.logonID) AS MaxlogonIDs
FROM clients c
INNER JOIN LogOnsLink ll ON ll.clientID=c.clientID
WHERE c.entity LIKE '%Com%'
GROUP BY entity
ORDER BY entity
or
SELECT DISTINCT entity
FROM clients c
INNER JOIN LogOnsLink ll ON ll.clientID=c.clientID
WHERE c.entity LIKE '%Com%'
ORDER BY entity
Try this
SELECT ll.logonID, DISTINCT(entity)
FROM Clients c INNER JOIN LogOnsLink ll
ON ll.clientID=c.clientID
WHERE c.entity LIKE '%Com%'
ORDER BY entity

Sql Query Join in Oracle

I have Parent table and multiple child tables with foreign key constraint.
School Table
School ID EduDetails Genders Address_id EDUTYPE
1 2 M 3 FGN
And the child tables like
Education Details
EDU ID EducationType
2 Online
AKA Name
School Id AKA Name
1 Test School
1 School Test
Gender Table
Gender ID Gender Desc
M Male
I am using Left outer join for the parent and school table to fetch the results.
But My issue is, If AKA table has 5 counts matching the school Id and Gender table has only 1 records for that school Id.
So the results comes with 5 duplicate rows with school Information and also other child table information.
Is there any workaround to fix this issue. I tried using subquery and row_number over by function. But it is not working for me. Can anybody help me to solve this issue.
Thanks in advance for your time in looking this issue.
My required output should be like this
School_id AKA Name GenderDesc EductaionType
1 Test School Male Online
1 School Test
So I need to have Null values for the not matching records.
Since you want all the records in the AKA Name table, I've joined on that getting a Row_Number for each row. Then using that Row_Number, LEFT JOIN on the other tables.
SELECT S.SchoolId,
SA.AKAName,
G.GenderName,
ED.EducationType
FROM School s
JOIN
(SELECT SchoolId,
AKAName,
ROW_NUMBER() OVER (PARTITION BY SchoolId ORDER BY AKAName) rn
FROM SchoolAKA
) SA ON S.SchoolID = SA.SchoolId
LEFT JOIN
(SELECT EDUID,
EducationType,
ROW_NUMBER() OVER (ORDER BY EducationType) rn
FROM EduDetails
) ED ON S.EDUID = ED.EDUID AND SA.rn = ED.rn
LEFT JOIN
(SELECT GenderId,
GenderName,
ROW_NUMBER() OVER (ORDER BY GenderName) rn
FROM Genders
) G ON S.GenderId = G.GenderId AND SA.rn = G.rn
Here is the SQL Fiddle.
And here are the results:
SCHOOLID AKANAME GENDERNAME EDUCATIONTYPE
1 School Test Male Online
1 Test School (null) (null)