HQL Path expected for join (when joining same table) - c#

I am trying to get pairs of measurement for two different devices, joined on equal Timestamps. In SQL, this works as expected:
select
leftItem.Timestamp, leftItem.Value, rightItem.Value
from
DataTable leftItem
inner join DataTable rightItem
on leftItem.Timestamp = rightItem.Timestamp
where
leftItem.Device = 1 and rightItem.Device = 2
But if I try to convert it to HQL:
select
left, right
from
DataTable as left
inner join DataTable as right
on left.Timestamp = right.Timestamp
where
left.Device = 1 and right.Device = 2
I get a NHibernate.Hql.Ast.ANTLR.SemanticException:
Path expected for join!
How do I specify a "path" to the same table?

In HQL, joins can only be done on associations between entities. If you want a join on something else, the only possibility is to make the join in the where clause:
select left, right
from
DataTable as left, DataTable as right
where
left.Timestamp = right.Timestamp
and left.Device = 1
and right.Device = 2

Related

C# Linq Table query to count the non-matching entries

I am quite new to this, I am running two SQL queries and I am creating two separate data tables, DataTable1 and DataTable2.
I am applying some linq criteria to DataTable1 and creating another data table from that, which is DataTable3.
var Query3 = from table1 in DataTable1.AsEnumerable()
where table1.Field<DateTime>("DateTime") <= Yday
where table1.Field<string>("StockCode").Contains("-CA") && !(table1.Field<string>("StockCode").Contains("-CAB")) ||
table1.Field<string>("StockCode").Contains("-CM") ||
table1.Field<string>("StockCode").Contains("-LP")
select table1;
DataTable DataTable3 = Query3.CopyToDataTable()
Now I would write another query to do the following.
Both data tables have a column JobNumber. I would like to query DataTable3 in DataTable 2 to count the rows that have similar JobNumber entries. Below is what I am doing but I am not getting the correct count.
int count = (from table3 in DataTable3.AsEnumerable()
join table2 in DataTable2.AsEnumerable() on table2.Field<string>("JobNumber") equals table3.Field<string>("JobNumber")
where table2.Field<string>("JobNumber") == table3.Field<string>("JobNumber")
select table2).Count();
You are creating a cartesian join and counting its result, was that what you indented ? Also in your linq your Join expression and where expression is same (where is redundant). It is not clear what you really want to count. Probably you instead wanted to count those in DataTable2 where JobNumbers exists in DataTable3?:
var jobNumbers = (from r in DataTable3.AsEnumerable()
select r.Field<string>("JobNumber")).ToList();
var count = (from r in DataTable2.AsEnumerable()
where jobNumbers.Contains( r.Field<string>("JobNumber") )
select r).Count();
As a side note, it would be much easier if you used Linq To SQL instead (rather than Linq To DataSet).

Linq return distinct values from table if not exist in another

I am trying to return all distinct rows from Staging below where Staging.CenterCode does not exist in Centers.CenterCode.
At the moment Stagings has around 850 distinct CenterCodes and Centers is empty so I should be getting all of the distinct rows, but count begs to differ :)
Any ideas?
var query =
(from s in db.Stagings
join t in db.Centers on s.CenterCode equals t.CenterCode into tj
from t in tj.DefaultIfEmpty()
where s.CenterCode != t.CenterCode
select s.CenterCode).Distinct();
var c = query.Count();
I only need the unique columns from staging so not sure if I actually need a join with the above as I am not ever using data returned from Centers - I have however tried both and get the same 0 value for count.
Any ideas?
I would not use a join, but use a Contains.
var centerCodesQuery = db.Centers.CenterCode
.Select(x => x.CenterCode);
var query = db.Staging
.Where(x => !centerCodesQuery.Contains(x.CenterCode))
.Select(x => x.CenterCode)
.Distinct();
var c = query.Count();
the join is an inner join. So, if none of the rows in 1 table match the other table on the specified identifier then it will return 0. In yours you are trying to join 1 table with 850 distinct rows with an empty table. This will return 0.
If you actually want to return only those rows in 1 table that aren't in another you can use Except:
var query = (from s in db.Stagings
select s.CenterCode)
.Except(from t in db.Centers
select t.CenterCode);
var c = query.Count();
Looks like you are trying to implement antijoin via left outer join, which is one of the possible ways, but in order to make it work, you need to change
where s.CenterCode != t.CenterCode
to
where t == null

Average numbers in my SQL query

I have a question regarding my SQL query. Below you will see my database:
And I have the following query right now:
SELECT enquete_vraag,enquete_antwoord,docent,vak,semesterstart
FROM ENQUETE_ANTWOORD
LEFT JOIN KDV ON ENQUETE_ANTWOORD.kdv_ID = KDV.kdv_ID
LEFT JOIN DOCENT ON KDV.docent_ID = DOCENT.docent_ID
LEFT JOIN VAK ON KDV.vak_ID = VAK.vak_ID
LEFT JOIN ENQUETE_VRAAG ON ENQUETE_ANTWOORD.enquete_vraag_ID = ENQUETE_VRAAG.enquete_vraag_ID
WHERE DOCENT.docent_ID = variableDocentID AND VAK.vak = variableVak
And I display the returned data in a datagridview:
Now the datagridview shows all questions that are being answered by all students. What I want is the average for each question and only show that. So you have 1 row that has question 6 with the average answer and question 7 with the average answer and so on, how do I achieve that in my SQL query?
hi you should do something like this
SELECT enquete_vraag,AVG(enquete_antwoord) enquete_antwoord,docent,vak,semesterstart
FROM ENQUETE_ANTWOORD
LEFT JOIN KDV ON ENQUETE_ANTWOORD.kdv_ID = KDV.kdv_ID
LEFT JOIN DOCENT ON KDV.docent_ID = DOCENT.docent_ID
LEFT JOIN VAK ON KDV.vak_ID = VAK.vak_ID
LEFT JOIN ENQUETE_VRAAG ON ENQUETE_ANTWOORD.enquete_vraag_ID = ENQUETE_VRAAG.enquete_vraag_ID
WHERE DOCENT.docent_ID = variableDocentID AND VAK.vak = variableVak
GROUP BY enquete_vraag, docent,vak,semesterstart
SELECT enquete_vraag,AVG(enquete_antwoord) as [enquete_antwoord]
FROM ...
GROUP BY enquete_vraag
The problem then, of course, becomes which vak etc to choose.... Because of translation, it is not easy for me to guess at which value means what, so it is hard to advise on that. You might be able to include the extra values in the GROUP BY clause (if they are the same for all the matching rows); or you might be able to take a MIN / MAX.
just add avg function in your code.
...AVG(enquete_antwoord)...
write above code it gives you the correct answer

How do I use multiple IDs from a table with an INNER JOIN using SQL?

I have a list of SiteUsers in one table and another table has columns with different types of owners (ID) for the record. For example, the SiteUserID in the SiteUsers table will be used for the SalesRepID, the StaffingManagerID, and RecruiterID in the Fill table. Of course, the SiteUserID is different for each of the values in the Fill table.
I'd like to return the name of the SiteUser for each ID column in the Fill Table.
How do I properly construct a JOIN statement to do this?
I'm guessing this is done through INNER JOIN, but I'm not sure.
My current select statement already has an INNER JOIN as I'm pulling the name of the FillType from another table. I'm using this in an asp.net application.
I'm not sure if this is even possible. Any help is appreciated.
Since each of the IDs in the Fills table allows null, you probably want to LEFT JOIN to the SiteUsers table like so:
SELECT f.FillID, s1.SiteUserLastName 'SalesRep', s2.SiteUserLastName 'StaffingManager', s3.SiteUserLastName 'Recruiter'
FROM Fills f
LEFT JOIN SiteUsers s1 on f.SalesRepID = s1.SiteUserID
LEFT JOIN SiteUsers s2 on f.StaffingManagerID = s2.SiteUserID
LEFT JOIN SiteUsers s3 on f.RecruiterID = s3.SiteUserID
You can always UNPIVOT the results like so:
SELECT
DISTINCT
unpvt.FillID
,unpvt.RepID
,unpvt.RepType
,s.SiteUserFirstName
,s.SiteUserLastName
FROM
(SELECT
FillID
,SalesRepID
,StaffingManagerID
,RecruiterID
FROM Fills
) f
UNPIVOT
(RepID FOR RepType IN
(SalesRepID, StaffingManagerID,RecruiterID)
) AS unpvt
JOIN SiteUsers AS s on unpvt.RepID = s.SiteUserID`
Obviously you can play with exact output (such as substituting the RepType for a different value with a CASE statement or whatnot.
My question is: why the piss-poor design? Instead of having three IDs in the Fills table, you should have a junction table between SiteUsers and Fills to allow many-to-many relationships. IF it were designed with a junction table, you'd never have had to ask this question.
You will have to join the Fill table with the SiteUsers table multiple times, one for each xxxID column in the Fills for which you want the SiteUser name and combine the results using an union as below:
select a.SiteUserId, a.SiteUserFirstName, a.SiteUserLastName
from dbo.SiteUsers a
inner join dbo.Fills b on b.SalesRepId = a.SiteUserId
UNION
select a.SiteUserId, a.SiteUserFirstName, a.SiteUserLastName
from dbo.SiteUsers a
inner join dbo.Fills b on b.StaffingManagerId = a.SiteUserId
UNION
select a.SiteUserId, a.SiteUserFirstName, a.SiteUserLastName
from dbo.SiteUsers a
inner join dbo.Fills b on b.RecruiterId = a.SiteUserId

How do I join tables with a condition using LLBLGen?

I have the following Sql Query that returns the type of results that I want:
SELECT b.ID, a.Name, b.Col2, b.COl3
FROM Table1 a
LEFT OUTER JOIN Table2 b on b.Col4 = a.ID AND b.Col5 = 'test'
In essence, I want a number of rows equal to Table1 (a) while having the data from Table2 (b) listed or NULL if the condition, 'test', doesn't exist in Table2.
I'm rather new to LLBLGen and have tried a few things and it isn't working. I can get it to work if the condition exists; however, when a requirements change came in and caused me to rewrite the query to that above, I'm at a loss.
Below is the old LLBLGen C# code that worked for existing products but not for the above query:
LookupTable2Collection table2col = new LookupTable2Collection();
RelationCollection relationships = new RelationCollection();
relationships.Add(LookupTable2Entity.Relations.LookupTable1EntityUsingTable1ID, JoinHint.Left);
IPredicateExpression filter = new PredicateExpression();
filter.Add(new FieldCompareValuePredicate(LookupTable2Fields.Col5, ComparisonOperator.Equal, "test"));
table2col.GetMulti(filter, relationships);
Table 1 has 3 records in it. I need the 3 records back even if all items from Table 2 are NULL because the condition doesn't exist. Any ideas?
You've to add your filter to the relation join like this:
relationships.Add(LookupTable2Entity.Relations.LookupTable1EntityUsingTable1ID, JoinHint.Left).CustomFilter = new FieldCompareValuePredicate(LookupTable2Fields.Col5, ComparisonOperator.Equal, "test");

Categories