How to join Two tables of two non relashinship defined columns using Nhibernate QueryOver - nhibernate

Using NHibernate QueryOver, I want to join two tables using two columns which are not defined in the mapping as a relationship.
E.g. This is not my exact scenario but this can explain that
Tables:
Employee(Id, Name, DepartmentId, SomeCode,Address)
Department (Id, Name, ,Code)
Select
SELECT *
FROM EMPLOYEE E
JOIN DEPARTMENT D
ON D.Code = E.SomeCode
Can someone please tell me how to do this query using NHibernate QueryOver. Note that "SomeCode" in Employee and "Code" in Department are not defined as a relationship. DepartmentId is the foreign key and I can join these using JoinAlias but I want it in a somewhat different way.

There are similar questions, e.g.
NHibernate (+ FluentNhibernate) : Join two detached tables
Hibernate Criteria Projection without mapped association of tables
And the answer is:
either use HQL and CROSS JOIN (with WHERE)
There is NO way how to do that with QueryOver/Criteria)
See the doc:
14.2. The from clause
Multiple classes may appear, resulting in a cartesian product or "cross" join.
from Formula, Parameter
from Formula as form, Parameter as param
So using HQL in your case, we can do it like this:
SELECT ...
FROM EMPLOYEE E, DEPARTMENT D
WHERE D.Code = E.SomeCode
...
BUT I would suggest: create that mapping in the code. Simply introduce many-to-one relation. It will be loaded lazily (only if used) and will nicely serve to our needs - be used in QueryOver as a relation for Join
If there is such relation, if this exist in the business object domain, we should not be scared to use it. We can hide it via security etc...

Related

writing sql query between tables

Which SQL query could I write to satisfiy this need:
"List the names of the students who take a course from instructor named John."
Not sure that you can, from the depicted relations.
You can identify tutors by selecting on InstructorID and filtering on Instructor.FirstName.
You can join that subset onto course, via the InstructorCourses Join Table - join InstructorID to that and join the result to Courses using CourseID
In this way, Instructor.InstructorID -> (InstructorCourses.InstructorID , InstructorCourses.CourseID ) -> Courses.CourseID.
This lets you find information about the courses taught by instructors filtered on their name.
You don't present any link between students and courses in your diagram. I suspect you're missing a relation StudentCourses, which ought to be similar to InstructorCourses, but rather links students to courses. With that data in the mix, you can extend the join to match students to the courses from the relationship you already have.
Your diagram implies a relation between Student and InstructorCourses, which seems incorrect - both because there is no key to join on, and also because the logical relationship would not be correct. I think this is probably an error.
It is impossible to satisfy the SQL query you need because your conception does not allow it in that there is no relationship between the 2 tables Student and InstructorCourses.

Joins explained by Venn Diagram with more than one join

http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
and
https://web.archive.org/web/20120621231245/http://www.khankennels.com/blog/index.php/archives/2007/04/20/getting-joins/
have been very helpful in learning the basics of joins using Venn diagrams. But I am wondering how you would apply that same thinking to a query that has more than one join.
Let's say I have 3 tables:
Employees
EmployeeID
FullName
EmployeeTypeID
EmployeeTypes (full time, part time, etc.)
EmployeeTypeID
TypeName
InsuranceRecords
InsuranceRecordID
EmployeeID
HealthInsuranceNumber
Now, I want my final result set to include data from all three tables, in this format:
EmployeeID | FullName | TypeName | HealthInsuranceNumber
Using what I learned from those two sites, I can use the following joins to get all employees, regardless of whether or not their insurance information exists or not:
SELECT
Employees.EmployeeID, FullName, TypeName, HealthInsuranceNumber
FROM Employees
INNER JOIN EmployeeTypes ON Employees.EmployeeTypeID = EmployeeTypes.EmployeeTypeID
LEFT OUTER JOIN InsuranceRecords ON Employees.EmployeeID = InsuranceRecords.EmployeeID
My question is, using the same kind of Venn diagram pattern, how would the above query be represented visually? Is this picture accurate?
I think it is not quite possible to map your example onto these types of diagrams for the following reason:
The diagrams here are diagrams used to describe intersections and unions in set theory. For the purpose of having an overlap as depicted in the diagrams, all three diagrams need to contain elements of the same type which by definition is not possible if we are dealing with three different tables where each contains a different type of (row-)object.
If all three tables would be joined on the same key then you could identify the values of this key as the elements the sets contain but since this is not the case in your example these kind of pictures are not applicable.
If we do assume that in your example both joins use the same key, then only the green area would be the correct result since the first join restricts you to the intersection of Employees and Employee types and the second join restricts you the all of Employees and since both join conditions must be true you would get the intersection of both of the aforementioned sections which is the green area.
Hope this helps.
That is not an accurate set diagram (either Venn or Euler). There are no entities which are members of both Employees and Employee Types. Even if your table schema represented some kind of table-inheritance, all the entities would still be in a base table.
Jeff's example on the Coding Horror blog only works with like entities i.e. two tables containing the same entities - technically a violation of normalization - or a self-join.
Venn diagrams can accurately depict scenarios like:
-- The intersection lens
SELECT *
FROM table
WHERE condition1
AND condition2
-- One of the lunes
SELECT *
FROM table
WHERE condition1
AND NOT condition2
-- The union
SELECT *
FROM table
WHERE condition1
OR condition2

how to map a bag/list/set in a class from a table which is got an indirect link to a table

I know the title might sound a bit weird but I've attached a screen of the database design. I have two master tables with a many-to-many relationship in between. But we're using the primary key from the many-to-many table to refer another table called ResourceAllcoation table with the foreign key (ProjectResourceID)
Now what would be the best way to get a bag of ResourceAllocation in the Resource entity? Is there a direct way to do this in nhibernate?
Currently my nhibernate mapping has a one-to-many bag to the ProjectResource table which is then referring the ResourceAllocation table which I feel might not be the best approach.
Please forgive my ignorance. Any thoughts is appreciated.
#kalki, when I implemented your mapping, I figured that the sql query getting generated is
SELECT
*
FROM PROJECTRESOURCE P
LEFT OUTER JOIN RESOURCEALLOCATION R
ON P.PROJECTRESOURCEID=R.ID WHERE P.RESOURCEID=1
but that doesn't work since ProjectResource doesn't have a PROJECTRESOURCEID column
If the query generated was
SELECT *
FROM PROJECTRESOURCE P
LEFT OUTER JOIN RESOURCEALLOCATION R
ON P.ID = R.PROJECTRESOURCEID
WHERE P.RESOURCEID=1
it would work.
You can map this using a Many-to-Many in NHibernate and an IdBag

How to design the database schema to link two tables via lots of other tables

Although I'm using Rails, this question is more about database design. I have several entities in my database, with the schema a bit like this: http://fishwebby.posterous.com/40423840
If I want to get a list of people and order it by surname, that's no problem. However, if I want to get a list of people, ordered by surname, enrolled in a particular group, I have to use an SQL statement that includes several joins across four tables, something like this:
SELECT group_enrolment.*, person.*
FROM person INNER JOIN member ON person.id = member.person_id
INNER JOIN enrolment ON member.id = enrolment.member_id
INNER JOIN group_enrolment ON enrolment.id = group_enrolment.enrolment_id
WHERE group_enrolment.id = 123
ORDER BY person.surname;
Although this works, it strikes me as a bit inefficient, and potentially as my schema grows, these queries could get more and more complicated.
Another option could be to join the person table to all the other tables in the query by including person_id in the other tables, then it would just be one single join, for example
SELECT group_enrolment.*, person.*
FROM person INNER JOIN group_enrolment ON group_enrolment.person_id
WHERE group_enrolment.id = 123
ORDER BY person.surname;
But this would mean that in my schema, the person table is joined to a lot of other tables. Aside from a complicated schema diagram, does anyone see any disadvantages to this?
I'd be very grateful for any comments on this - whether what I'm doing now (the many table join) or the second solution or another one that hasn't occurred to me is the best way to go.
Many thanks in advance
Well, joins are what databases do. Having said that, you may consider propagating natural keys in your model, which would then allow you to skip over some tables in joins. Take a look at this example.
EDIT
I'm not saying that this will match your model (problem), but just for fun try similar queries on something like this:

Weird many to many and one to many relationship

I know I'm gonna get down votes, but I have to make sure if this is logical or not.
I have three tables A, B, C. B is a table used to make a many-many relationship between A and C. But the thing is that A and C are also related directly in a 1-many relationship
A customer added the following requirement:
Obtain the information from the Table B inner joining with A and C, and in the same query relate A and C in a one-many relationship
Something like:
alt text http://img247.imageshack.us/img247/7371/74492374sa4.png
I tried doing the query but always got 0 rows back. The customer insists that I can accomplish the requirement, but I doubt it. Any comments?
PS. I didn't have a more descriptive title, any ideas?
UPDATE:
Thanks to rcar, In some cases this can be logical, in order to have a history of all the classes a student has taken (supposing the student can only take one class at a time)
UPDATE:
There is a table for Contacts, a table with the Information of each Contact, and the Relationship table. To get the information of a Contact I have to make a 1:1 relationship with Information, and each contact can have like and an address book with; this is why the many-many relationship is implemented.
The full idea is to obtain the contact's name and his address book.
Now that I got the customer's idea... I'm having trouble with the query, basically I am trying to use the query that jdecuyper wrote, but as he warns, I get no data back
This is a doable scenario. You can join a table twice in a query, usually assigning it a different alias to keep things straight.
For example:
SELECT s.name AS "student name", c1.className AS "student class", c2.className as "class list"
FROM s
JOIN many_to_many mtm ON s.id_student = mtm.id_student
JOIN c c1 ON s.id_class = c1.id_class
JOIN c c2 ON mtm.id_class = c2.id_class
This will give you a list of all students' names and "hardcoded" classes with all their classes from the many_to_many table.
That said, this schema doesn't make logical sense. From what I can gather, you want students to be able to have multiple classes, so the many_to_many table should be where you'd want to find the classes associated with a student. If the id_class entries used in table s are distinct from those in many_to_many (e.g., if s.id_class refers to, say, homeroom class assignments that only appear in that table while many_to_many.id_class refers to classes for credit and excludes homeroom classes), you're going to be better off splitting c into two tables instead.
If that's not the case, I have a hard time understanding why you'd want one class hardwired to the s table.
EDIT: Just saw your comment that this was a made-up schema to give an example. In other cases, this could be a sensible way to do things. For example, if you wanted to keep track of company locations, you might have a Company table, a Locations table, and a Countries table. The Company table might have a 1-many link to Countries where you would keep track of a company's headquarters country, but a many-to-many link through Locations where you keep track of every place the company has a store.
If you can give real information as to what the schema really represents for your client, it might be easier for us to figure out whether it's logical in this case or not.
Perhaps it's a lack of caffeine, but I can't conceive of a legitimate reason for wanting to do this. In the example you gave, you've got students, classes and a table which relates the two. If you think about what you want the query to do, in plain English, surely it has to be driven by either the student table or the class table. i.e.
select all the classes which are attended by student 1245235
select all the students which attend class 101
Can you explain the requirement better? If not, tell your customer to suck it up. Having a relationship between Students and Classes directly (A and C), seems like pure madness, you've already got table B which does that...
Bear in mind that the one-to-many relationship can be represented through the many-to-many, most simply by adding a field there to indicate the type of relationship. Then you could have one "current" record and any number of "history" ones.
Was the customer "requirement" phrased as given, by the way? I think I'd be looking to redefine my relationship with them if so: they should be telling me "what" they want (ideally what, in business domain language, their problem is) and leaving the "how" to me. If they know exactly how the thing should be implemented, then I'd be inclined to open the source code in an editor and leave them to it!
I'm supposing that s.id_class indicates the student's current class, as opposed to classes she has taken in the past.
The solution shown by rcar works, but it repeats the c1.className on every row.
Here's an alternative that doesn't repeat information and it uses one fewer join. You can use an expression to compare s.id_class to the current c.id_class matched via the mtm table.
SELECT s.name, c.className, (s.id_class = c.id_class) AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
JOIN c ON (c.id_class = mtm.id_class);
So is_current will be 1 (true) on one row, and 0 (false) on all the other rows. Or you can output something more informative using a CASE construct:
SELECT s.name, c.className,
CASE WHEN s.id_class = c.id_class THEN 'current' ELSE 'past' END AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
JOIN c ON (c.id_class = mtm.id_class);
It doesn't seem to make sense. A query like:
SELECT * FROM relAC RAC
INNER JOIN tableA A ON A.id_class = RAC.id_class
INNER JOIN tableC C ON C.id_class = RAC.id_class
WHERE A.id_class = B.id_class
could generate a set of data but inconsistent. Or maybe we are missing some important part of the information about the content and the relationships of those 3 tables.
I personally never heard a requirement from a customer that would sound like:
Obtain the information from the Table
B inner joining with A and C, and in
the same query relate A and C in a
one-many relationship
It looks like that it is what you translated the requirement to.
Could you specify the requirement in plain English, as what results your customer wants to get?