How to add a Restriction to an inner join? - c#

I have the following NHibernate DetatchedCriteria,
return DetachedCriteria.For<MMFund>()
.CreateCriteria<MMFund>(x => x.DataUniverse)
.Add<DataUniverse>(x => x.SiteId == 100)
.SetProjection(LambdaProjection.Property<MMFund>(x => x.FundId));
which is producing the following SQL:
and
this_.ShareClassReturn_ShareClassId in
(
SELECT f.[Fund_ID] as y0_
FROM
dbo.Fund f inner join CAP.DataUniverse du
on f.[Fund_TypeID] = du.[DataUniverse_TypeId]
and f.[Fund_CountryID] = du.[DataUniverse_CountryID]
WHERE fu.[DataUniverse_SiteId] = 100
)
There are many funds in a DataUniverse.
I need to filter this so that I can select only the funds with a country ID of 'ET', so that my query looks as follows:
and
scr.ShareClassReturn_ShareClassId in
(
/* Get funds in universe */
SELECT f.[Fund_ID] as y0_
FROM dbo.Fund f inner join CAP.DataUniverse du
on f.[Fund_TypeID] = du.[DataUniverse_TypeId]
and f.[Fund_CountryID] = 'ET' // these are the guys I need
WHERE du.[DataUniverse_SiteId] = 100
)
However, I'm not sure what I need to do to the DetachedCriteria in order to make this happen. The problem I'm having is that no matter what I do, it's putting the clause in the wrong place, such as
WHERE du.[DataUniverse_SiteId] = 100 and f.Fund_CountryId = 'ET'
when I add the line .Add(Restrictions.Eq("CountryId", "ET")) as follows
return DetachedCriteria.For<MMFund>()
.Add(Restrictions.Eq("CountryId", "ET"))
.CreateCriteria<MMFund>(x => x.DataUniverse)
.Add<DataUniverse>(x => x.SiteId == 100)
.SetProjection(LambdaProjection.Property<MMFund>(x => x.FundId));
or it attempts to filter on the wrong table entirely when I specify that the Restriction should be part of the second .CreateCriteria, such as
return DetachedCriteria.For<MMFund>()
.CreateCriteria<MMFund>(x => x.DataUniverse)
.Add(Restrictions.Eq("CountryId", "ET"))
.Add<DataUniverse>(x => x.SiteId == 100)
.SetProjection(LambdaProjection.Property<MMFund>(x => x.FundId));
which produces this;
WHERE du.[DataUniverse_SiteId] = 100 and du.[DataUniverse_CountryID] = 'ET'
** note - as I'm using the Criteria API, this is actually the Restriction that I'm using:
.Add<MMFund>(f => f.CountryId == "ET")
I used the Restriction terminology because it's more explicit to what I'm trying to achieve. The Criteria API & the other way both produce the exact same results.

Why do you think Where is the wrong place for the filter? That's where filtering happens.
The generated SQL looks sound. You have two tables joined on their common fields. The Where clause is providing the appropriate filtering information. If your preferred SQL statement was in place, you'd have data joined on TypeID alone, not the CountryID.
For example, let's say your Fund table looks like this
TypeID CountryID
1 1
1 2
2 1
2 2
3 1
4 1
And your DataUniverse table is the following
TypeID CountryID
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
4 1
4 2
If you wrote SQL like you desire, you would produce a join based on TypeID and you would filter Fund.CountryID = 1, for example. What would your product look like?
F.TypeID F.CountryID D.TypeID D.CountryID
1 1 1 1
1 1 1 2
1 1 1 3
2 1 2 1
2 1 2 2
2 1 2 3
3 1 3 1
3 1 3 2
4 1 4 1
4 1 4 2
Is that your desired output? Yes, you've filtered Fund.CountryID, but your join was just on TypeID, so you've got all records from DataUniverse with that matching type for each Fund.
With the join on the two fields and the Where filtering the CountryID, the result will be the following
F.TypeID F.CountryID D.TypeID D.CountryID
1 1 1 1
2 1 2 1
3 1 3 1
4 1 4 1
The question is which set of data is the one you expect?

Related

EF select many doesn't retrieve record which has no relation

I have two tables, for example, Student and Grade.
Those two tables have a relationship with many-to-many, so the table is StudentGrade.
By using the .SelectMany query, I can retrieve all records which have a relation.
For example,
var myResult = myDb.Student.SelectMany(x => x.Grade).ToList();
But let say I add a new record just to the Student table, which has no relation with Grade, this new record cannot be retrieved by using the query above.
How can I retrieve all data including this new one?
Student
Id Name Age
1 AAA 4
2 BBB 5
3 CCC 6
4 DDD 7
Grade
Id Name
1 G1
2 G2
3 G3
4 G4
StudentGrade
Student Grade
2 1
2 2
2 3
3 3
Require result:
Id Name Age Grade
1 AAA 4
2 BBB 5 G1
2 BBB 5 G2
2 BBB 5 G3
3 CCC 6 G3
4 DDD 7
I found full outer join would help but will it work in a many-to-many relationship?
How can I overcome this issue ?
var result = (from s in myDb.Student
from g in myDb.Grades
where !g.Select(x => x.Student).Contains(s) || g.Student == null || g.Student == s).ToList();
As long as I understand your question this should give you
all Students that have grades,
all Grades with no students,
and all Students with no grades.
I have not seen your models but this should help
var myResult = myDb.Student.SelectMany(x => x.Grade).ToList();
This query "means" retrieve all the Grades that have a Student. If you want the Students, select Student and Include the Grades if you want.
var myResult = myDb.Students.Include(x => x.Grades).ToList();

SQL hiearchy select query between two tables

I have 2 tables (People, Department).
Department table look like this:
ID (int)
Name (varchar)
ParentID (int)
People table like this:
Id (int)
FirstName (varchar)
SureName (varchar)
DepartmentId (int)
Manager (Bool)
Asistant (Bool)
I need to create query, which select all direct subordinates of concrete person which is manager of concrete depertment. And one query which select all not only direct subordinates of manager.
Each department have one manager and one asistant. The peoples with manager == false are direct subordinates, and peoples in child depertment are subordinates of parent depratment .
I have no idea how to crete this queries in SQL / LINQ.
I will be grateful for any help!
Example:
DEPARTMENT
Id Name Parent
0 Department1 null
1 Department2 0
2 Department3 1
Example:
People
ID Name Department DepartmentId Manager Asistant
1 Martin Joshua 0 1 0
2 Ondra Joshua2 0 0 0
3 Petr Joshua3 0 0 0
4 Todd Joshua3 1 1 0
5 Alex Joshua3 1 0 0
6 Iva Joshua3 1 0 0
7 Otto Joshua3 2 1 0
8 Todd Joshua3 2 0 0
I need for exmple select all (not only direct) subordinates of manager in deparment with id 0, result wil look like:
2 Ondra Joshua2 0 0 0
3 Petr Joshua3 0 0 0
4 Todd Joshua3 1 1 0
5 Alex Joshua3 1 0 0
6 Iva Joshua3 1 0 0
7 Otto Joshua3 2 1 0
8 Todd Joshua3 2 0 0
I´m not sure direct subordinates SQL query:
SELECT * FROM dbo.PeopleView WHERE DepartmentId = 162 AND Manager = 0; -- all direct s (162)
SOLUTION:
;WITH CTE AS
(
SELECT 1 as EMPLEVEL, H1.Id, H1.ParentId, H1.Name FROM DepartmentView H1 WHERE Id = 6
UNION ALL
SELECT EMPLEVEL + 1, H2.Id, H2.ParentId, H2.Name FROM DepartmentView H2
INNER JOIN CTE ON H2.ParentId = CTE.Id
)
SELECT DISTINCT P.Id, P.LastName,P.FirstName,P.DepartmentId,P.Manager,P.Assistant FROM CTE as T JOIN PeopleView as P on T.Id = P.DepartmentId;
In adition to your first query, and like a comment from #Andrew says, a recursive query can help with this:
;WITH CTE
AS
(
SELECT ID,FirstName,SureName,DepartmentID,Manager,Assistant, 0 AS EMPLEVEL FROM PEOPLE A WHERE DepartmentId = 1 AND Manager = 0
UNION ALL
SELECT B.ID,B.FirstName,B.SureName,B.DepartmentID,B.Manager,B.Assistant,EMPLEVEL +1 FROM PEOPLE B
INNER JOIN DEPARTMENT D
ON B.DepartmentID = D.ID
INNER JOIN CTE
ON D.ParentID = CTE.DepartmentID
)
SELECT DISTINCT * FROM CTE
And for convert to LINQ, you can read this post :P:
Common Table Expression (CTE) in linq-to-sql?
Hope this help, best regards.

Problems in Right join in SQl

I have the following table structure also i have mention my expected output
please help me with query as i dont know much about sql query
Table Structure
Table 1 : Emp Details
FName Id
Pratik 1
Praveen 3
Nilesh 2
Table 1 : JoinigDocument
id DocumentName
1 Leaving
2 Exp letter
3 birth cert
Table 2 : EmployeeJoiningDocument
EmpId JoiningDocumentId
1 1
1 2
3 1
3 2
3 3
2 1
2 3
Expected Output :
FName Id JoiningDocumentId DocumentName
Pratik 1 1 Leaving
Pratik 1 2 Exp letter
Pratik 1 null birth cert
Praveen 3 1 Leaving
Praveen 3 2 Exp letter
Praveen 3 3 birth cert
Nilesh 2 1 Leaving
Nilesh 2 null Exp letter
Nilesh 2 3 birth cert
You can write a query as:
select
A.FName,
A.Id,
B.JoiningDocumentId,
c.DocumentName
from #JoinigDocument C
cross join #EmployeeDetail A
Left join #EmployeeJoiningDocument B on B.EmployeeId = A.id and
B.JoiningDocumentId = C.id
order by A.Id
First cross join JoinigDocument and EmployeeDetail table so that you get all possible combinations of Employee and Documents irrespective of the fact that employee has that Joining Document or not. Then you need to do a left join to retain all these matches and find data corresponding to valid entries in EmployeeJoiningDocument.
Demo

How to concat with linq?

I have this tables at sql server:
id_service name
1 ejemplo 1
2 ejemplo 2
id_service id_quality
1 1
1 2
id_quality quality
1 simple
2 full
and Im trying to get this:
id_service qualities
1 Simple \n Full
I´m working with linq, is there any way to do it???
I have this so far, but it returns two rows instead of one as I need
var services = from service in dc.service
join s_quality in dc.service_quality
on service.id_service equals s_quality.id_service
join qualityObj in dc.quality
on s_quality.id_quality equals qualityObj.id_quality
select new {service.id_service, qualityObj.quality1};
GridView1.DataSource = services;
GridView1.DataBind();
The ending grid should look like this:
id_service name quality available
1 Company 1 1 - simple
2 - full
--------------------------------------------------------
2 Company 2 1 - simple
(this column should have grouped or concat results)
var servicios = from servicio in dc.servicio
join s_calidad in dc.servicio_calidad
on servicio.id_servicio equals s_calidad.id_servicio
join calidadObj in dc.calidad
on s_calidad.id_calidad equals calidadObj.id_calidad
group new {servicio.id_servicio, calidadObj.calidad1} by servicio.id_servicio into grouping
select new { groupning.Key, Concat = string.Join(",", grouping.Select(g => g.calidad1)) };
You can write your own concatenation logic for Concat property in the anonimous type

SQL query to get matching records from Table1 and Table2 with a custom column showing 1/0 if data is present

I have several table related to multilingual Photo Galley like
AlbumCategories
AlbumName
Photos
PhotoDetails
Sample Table Structure of two table. I actually want a result set that will show me list of all records from Photos Table for particular AlbumID along with a custom column that will show TRUE or FALSE based on if particular PhotoID is present in the PhotoDetails Table
Table: Photos
PhotoID PhotoFile AlbumID
1 Photo1.jpg 7
2 Photo2.jpg 7
3 Photo3.jpg 5
4 Photo4.jpg 5
5 Photo5.jpg 7
6 Photo6.jpg 7
Table: PhotoDetails
PDID PhotoID PDTitle AlbumID LanguageID
11 1 Photo 1 7 1
22 2 Photo 2 7 1
33 3 Photo 3 5 1
44 4 Photo 4 5 1
DESIRED OUT PUT
PhotoID PDTitle AlbumID DetailPresent
1 Photo1 7 TRUE
2 Photo2 7 TRUE
5 Photo5 7 FALSE
6 Photo6 7 FALSE
I tried something several JOIN based queries but could not get the desired result
SELECT pd.PhotoTitle, p.PhotoTN,p.PhotoCreatedOn, pd.AlbumID, ISNULL(p.PhotoID,NULL) AS Missing FROM AlbumPhotos p
JOIN AlbumPhotoDetails pd
ON p.PhotoID = pd.PhotoID WHERE pd.AlbumID = 16
This query gives me the same result
SELECT pd.PhotoTitle, p.PhotoTN,p.PhotoCreatedOn, pd.AlbumID, ISNULL(p.PhotoID,NULL) AS Missing FROM AlbumPhotos p
JOIN AlbumPhotoDetails pd
ON p.PhotoID = pd.PhotoID WHERE pd.AlbumID = 16
OR p.PhotoID IN (SELECT PhotoID FROM AlbumPhotoDetails WHERE LanguageID = 1 AND AlbumID = 16)
Above query get me the result of matching based on PhotoID. I am lost how i can actually achieve the desired result as shown in the above sample 'DESIRED OUT PUT`
Use a left outer join.
The table examples that you have shown doesn't make any sense, as there is no field to connect them, and the PDTitle values that you want in the result doesn't exist in the example data.
Assuming that there is a PhotoId field in the PhotoDetails table (like in the AlbumPhotoDetails table that you use in the query that you show), and that the PhotoDetails table contains the titles that you want in the result, you can do like this:
select
p.PhotoId, d.PDTitle, p.AlbumId,
case when d.PhotoId is null then 'FALSE' else 'TRUE' end
from Photos p
left join PhotoDetails d on d.PhotoId = p.PhotoId
where p.AlbumId = 7
Note that the title will be null where there are no corresponding record in the PhotoDetails table.

Categories

Resources