Conditional Join - join 1 tables 2 ways - c#

I have a set of (not very well normalised or relational) tables named
PLAN,
GROUP,
PRODUCT
CLIENT
Most have linkage i.e.
PLAN -> CLIENT on clno
GROUP to PRODUCT on PRODCD
However, the linkage between PLAN and GROUP is tricky. A plan has 2 field of interest GRPNO and PRODCD.
What I want to do is if GRPNO != 0 then join GROUP on GRPNO. However if GRPNO = 0 then I want to join GROUP on PRODCD.
The frustrating thing is that the fileds I want to return in my queries are the same across the board I just need to be able to vary the join, or join the same table twice.
The best I can come up with is 2 queries and merge them using datasets, or possibly using a union.
Is there a nifty way to do this in one select?
I should point out I am access Foxpro over ODBC to do this.
Thank you!

You can do:
JOIN GROUP AS G ON
(PL.GRPNO = 0 AND G.PRODCD = PL.PRODCD) OR
(PL.GRPNO !=0 AND G.GRPNO = PL.GRPNO)
However it would surprise me if this is faster than using UNION ALL.

Related

Keep getting error in my SQL code - "Column Invalid" [duplicate]

This question already has answers here:
GROUP BY / aggregate function confusion in SQL
(5 answers)
Closed 3 years ago.
I got an error -
Column 'Employee.EmpID' is invalid in the select list because it is
not contained in either an aggregate function or the GROUP BY clause.
select loc.LocationID, emp.EmpID
from Employee as emp full join Location as loc
on emp.LocationID = loc.LocationID
group by loc.LocationID
This situation fits into the answer given by Bill Karwin.
correction for above, fits into answer by ExactaBox -
select loc.LocationID, count(emp.EmpID) -- not count(*), don't want to count nulls
from Employee as emp full join Location as loc
on emp.LocationID = loc.LocationID
group by loc.LocationID
ORIGINAL QUESTION -
For the SQL query -
select *
from Employee as emp full join Location as loc
on emp.LocationID = loc.LocationID
group by (loc.LocationID)
I don't understand why I get this error. All I want to do is join the tables and then group all the employees in a particular location together.
I think I have a partial explanation for my own question. Tell me if its ok -
To group all employees that work in the same location we have to first mention the LocationID.
Then, we cannot/do not mention each employee ID next to it. Rather, we mention the total number of employees in that location, ie we should SUM() the employees working in that location. Why do we do it the latter way, i am not sure.
So, this explains the "it is not contained in either an aggregate function" part of the error.
What is the explanation for the GROUP BY clause part of the error ?
Suppose I have the following table T:
a b
--------
1 abc
1 def
1 ghi
2 jkl
2 mno
2 pqr
And I do the following query:
SELECT a, b
FROM T
GROUP BY a
The output should have two rows, one row where a=1 and a second row where a=2.
But what should the value of b show on each of these two rows? There are three possibilities in each case, and nothing in the query makes it clear which value to choose for b in each group. It's ambiguous.
This demonstrates the single-value rule, which prohibits the undefined results you get when you run a GROUP BY query, and you include any columns in the select-list that are neither part of the grouping criteria, nor appear in aggregate functions (SUM, MIN, MAX, etc.).
Fixing it might look like this:
SELECT a, MAX(b) AS x
FROM T
GROUP BY a
Now it's clear that you want the following result:
a x
--------
1 ghi
2 pqr
Your query will work in MYSQL if you set to disable ONLY_FULL_GROUP_BY server mode (and by default It is). But in this case, you are using different RDBMS. So to make your query work, add all non-aggregated columns to your GROUP BY clause, eg
SELECT col1, col2, SUM(col3) totalSUM
FROM tableName
GROUP BY col1, col2
Non-Aggregated columns means the column is not pass into aggregated functions like SUM, MAX, COUNT, etc..
Basically, what this error is saying is that if you are going to use the GROUP BY clause, then your result is going to be a relation/table with a row for each group, so in your SELECT statement you can only "select" the column that you are grouping by and use aggregate functions on that column because the other columns will not appear in the resulting table.
"All I want to do is join the tables and then group all the employees
in a particular location together."
It sounds like what you want is for the output of the SQL statement to list every employee in the company, but first all the people in the Anaheim office, then the people in the Buffalo office, then the people in the Cleveland office (A, B, C, get it, obviously I don't know what locations you have).
In that case, lose the GROUP BY statement. All you need is ORDER BY loc.LocationID

EntityFramework Linq Left Join Parsing Error - DotNet Core 1.0

I'm attempting to explicitly join 3 tables using a left outer join in a linq query and am running into linq parsing issues. Performing an inner join parses correctly and returns data but using the left outer fails.
Example:
var query = from p in DatabaseContext.Products
where p.ClientID == clientID
join l in DatabaseContext.Licenses on p.ProductID equals l.ProductID into pl
from pli in pl.DefaultIfEmpty()
join a in DatabaseContext.Articles on p.ArticleID equals a.ArticleID into pa
from pai in pa.DefaultIfEmpty()
select new SomeEntityDTO
{
SomethingFromP = p.Something,
SomethingFromL = pli.Something,
SomethingFromA = pai.Something
};
As both joined tables key off of the first table, I can test each individually by removing the other join, e.g., test the query for p to l and then for p to a. These test queries function perfectly. It's also possible to remove the left outer rule and receive a proper result.
var query = from p in DatabaseContext.Products
where p.ClientID == clientID
join l in DatabaseContext.Licenses on p.ProductID equals l.ProductID
join a in DatabaseContext.Articles on p.ArticleID equals a.ArticleID
select new SomeEntityDTO
... the rest ...
Viewing the offending query in SQL Profiler (top code example) I see that the first two tables are successfully joined, e.g.:
SELECT p.Something, l.Something
FROM Products AS p
LEFT JOIN Licenses AS l ON p.ProductID = l.ProductID
WHERE p.ClientID = 5
ORDER BY p.ProductID
And, then right after this successful query, are another 2 queries (identical to each other):
SELECT a.ArticleID, a.Something, <all fields, even when not specified in query>
FROM Articles AS a
ORDER BY a.ArticleID
The outer joined 3 tables will successfully return an object, as long as I don't attempt to access a field from the "a" table. When doing that, I recieve a Null Exception error, as that table was never really joined.
As stated, removing the outer join rule brings back a successfully joined query.
I have attempted to adjust the linq query figuring that the Linq parser had an issue, but to no avail:
var query = from p in DatabaseContext.Products
from l in DatabaseContext.Licenses.Where(g => g.ProduktID == p.ProduktID).DefaultIfEmpty()
from a in DatabaseContext.Articles.Where(g => g.ArticleID == p.ArticleID).DefaultIfEmpty()
where ....
This parses to a set of CROSS APPLYs that doesn't function at all and the profiled query, when copied into a query editor window, doesn't run at all (as opposed to the 3 individual queries seen in the profiler for the first code example). I have also attempted the more complicated lambdas, which also doesn't work.
Is this an error in the Linq parser? Am I doing this completely wrong? (According to the multiple answered questions here on explicit left outer joins (as opposed to natural associations), I'm doing it correctly. But, it doesn't parse correctly. I've avoided creating the associations so I can join them without explicitly defining the join. Is that potentially required here and won't work properly without it?
Note: Each table has complex keys but I only really need to join based on single key values (the DB is part of a product I can't change).
Using. DotNet Core, EntityFramework, EntityFrameworkCore.SqlServer, etc., all version 1.0.1.
Help?
The short answer is to use EF6 instead of EFCore if you absolutely have to have complex Linq queries on your entites, even after the 1.1 release. There are still too many things missing in EFCore compared to EF6.
Roadmap here.
In my case, I kept EFCore and used the Context.Entity.FromSql(query) method in order to get the results. This allowed me to utilize EFCore for most of the EF Entities, and thereby keeping a forward-looking approach to the application, while allowing for special exceptions for complicated queries not based on an actual entity. The plan is to replace those FromSql queries as EF Core matures.
Prior to deciding on .FromSql, I also tested a query on a View and on a stored procedure. In both instances, I failed. For stored procedures, named parameters is not yet implemented, and views are not currently supported unless you attempt to trick EF into thinking the view is actually a table (which brings its own issues).
In order to access EF Core .FromSql, you need to install the following package:
Microsoft.EntityFrameworkCore.Relational

Efficient way to count related entities of a many to many relation in EF

I would like to know how to efficiently count (SQL server side) the amount of distinct count of results for a specific range of a related entity that has a many to many relationship.
This is the current situation in entity Framework:
Table1 1<------->∞ Table2
Table2 ∞<------->∞ Table4
Table 2 and Table 4 have a many to many relationship and are linked with Table3 in SQL.
What I want is the distinct count of table4 results related to a specific range of Table1.
In LinQ to SQL the query is this:
(from dc in Table1
join vc in Table2 on dc.Table1Id equals vc.Table2Id
join vcac in Table3 on vc.Table2Id equals vcac.Table3Id
join ac in Table4 on vcac.Table3Id equals ac.Table4Id
where dc.Table1Id > 200000
group ac by ac.Table4Id into nieuw
select new { acid= nieuw.Key}).Count()
This lets SQL server return the count directly.
Because the extra table for the many to many relation ( Table3) is gone, I have had problems converting this query to L2E in query syntax. ( since I cannot join table 4 with table 2 with an inner join).
I have this in chained syntax, however, is this efficient ( does this fetch the whole list, or does it let SQLserver do the count, as I'm not sure this is an efficient way to select, Table 2 contains about 30.000 entries, I don't want it to fetch this result just to count it):
context.Table4.Where(a => a.Table2.Any(v => v.Table1Id > 200000)).Select(a => aTable4Id).Distinct().Count();
How would I go converting the Linq2SQL query into L2E in the query syntax ? Or is the chained syntax fine in this situation ?
The .Select() method uses deferred execution, meaning it won't actually run the query until you need the results. At that point in the chain it still exists only as a query definition. Then you modify with .Distinct() before getting .Count() - which does query the database using a SQL GROUP BY statement. So you should be good.

How to determine whether to use join in linq to sql?

I am just wondering about how we can determine whether to use join or not in linq to sql.
Eg. let say if we have two tables like this
Table 1 Customer
id
name
Table 2 addresstype
id
address1
customerid
and
var address = from cu in Customer
from ad in addresstype
where cu.id == ad.customerid
select ad;
or
var address = from cu in Customer
join ad in addresstype on cu.id equals ad.customerid
select de;
Is both way are the same. Is there any difference in performance?
Also the second method, will it come up with an error if there isn’t any matching?
Are you using linq to entities or linq to SQL? If its the former then you can avoid both of these by defining your relationships in the model and using navigation properties. This would be the clearest way of doing things
Basically, these two LINQ queries are equivalent to the following SQL queries:
select ad.*
from Customer cu, AddressType ad
where cu.ID == ad.CustomerID -- I assume this was meant by the OP
and
select ad.*
from Customer cu
inner join AddressType ad on cu.id = ad.CustomerID;
The difference between these two queries is mostly semantic, since the database will do the same thing in both cases and return a same result set for both queries.
I would prefer the join syntax in both SQL and LINQ since it defines an explicit relationship between the two tables/entities, that is only implied in the join-less version.
These are seems same query, they return same result but I don't know which one can be a faster, it should be bench marked.
But, In the case of linq2sql I prefer correlated subquery over join, because currently if you want t check the equation two element you should use syntax of:
new {X,Y} equals new {X',Y'}
in join and if you have more than this equations you should convert it to nested query. So I Prefer to have a more readable code which uses minimum differences in difference actions.
To throw a third and more prefered method into the mix with LINQ to SQL, use associations between the tables (even if you don't have them set up in your database). With that in place, you can navigate the object graph rather than using joins:
var query = from cu in Customer
from ad in cu.Addresses
select ad;
Note: when querying the object graphs, LINQ to SQL translates the join into a left outer join where-as the join/where syntax by default is an inner join.
Joins in LINQ should be used when there isn't a natural relationship between the objects. For example, use a join if you want to see the the listing of stores that are in the same city as your customers. (Join Customer.Address.City with Store.Address.City).
There should not be a difference between these two queries. I actually wondered this question myself a few months ago. I verified this through LINQPad. It's a free tool that you can download and actually see the generated SQL of any LINQ query (this is the query that is sent to the database).
The generated SQL should be the same for these two queries.
If you're doing this through Visual Studio, there is also a way you can see the generated SQL as well.

SQLCE: How to join tables from different SQLCE databases programmatically in C#?

I keep tables on different .sdf files because it's easy to manage them, ie; back up only changed db file, etc, plus in future db size might bigger and there is -4GB limit-
I need to join the tables and this will be my first -possibly LINQ- attempt. I know there are tons of examples/documents but a simple example would be nice to start.
This is the query for MS SQL Server:
SELECT personID, personPin, personName, seenTime
FROM db1.personList
LEFT JOIN db2.personAttendances on personID = seenPersonID
ORDER BY seenTime DESC
I think LINQ will be the way to go as you're querying across 2 different contexts. LINQ joins are quite easy: http://msdn.microsoft.com/en-gb/vcsharp/ee908647
Something like:
var q = from c in db1Context.personList
join p in db2Context.personAttendances on c.personID equals p.seenPersonID
select new { Category = c, p.ProductName };
I don't think SqlCE supports linking at the Db (SQL) level.
That means you'll have to use Linq-to-Objects. The example query has no WHERE clause so you can simply load the entire tables into Lists. But when the datasets get bigger that may not be acceptable.

Categories