Linq Left outer join Query - sql-server

How to convert this sql query into Linq query?
select *
from setupUOMs as su
LEFT OUTER JOIN scmSKUUoMs as ssu
on su.UoMID != ssu.UoMID
where ssu.SKUID = 446 and su.UMTypeID = 5
Following is the linq query.
from c in setupUOMs
join o in scmSKUUoMs
on c.UOMID equals o.UoMID into sr
from x in sr.DefaultIfEmpty()
where x.SKUID == 446
select x
In above query I've so far only done to extract the join number but what I want is to select the non equal records of left table but I'm able to show joined record. and it returns the records of only left table while my result is based on both columns. In where clause I can access x.SKUID which is from left table but can't access x.UMTypesID which is form right table (Means no column from right table is returned on which I can make condition).

Take a look at this LEFT JOIN LINQTOSQL Example.
http://www.devcurry.com/2011/01/linq-left-join-example-in-c.html
Maybe it will help.

A join with a non-equals condition is not a join but a Cartesian product excluding the inner joined records. There may be valid reasons to make a query as you did, but there's always a risk of blowing up the result set in terms of number of records.
So let's assume the conditions ensure a result that makes sense, then you can do:
from su in setupUOMs
from ssu in scmSKUUoMs // from .. from is a Cartesian product
where su.UOMID != ssu.UoMID
&& ssu.SKUID == 446
&& su.UMTypeID == 5
select new { su.Prop1, ssu.Prop2, ... }

Related

Inner Join returning wrong number of results

My query is returning 54 rows when it should return 59. I feel like I only need the Inner join because I wouldn't want to include NULL values in my results. I've also tried doing Left Outer Joins to filter out some of the non matching values but it returns too many results (62). I'm using DISTINCT so Duplicates shouldn't be the issue.
The query I'm trying to Create:
"List all ingredient classes and the titles of any recipes that use at least one
ingredient of that class, if any. Eliminate all duplicates. (2 columns, 59 rows)"
My Code:
select DISTINCT Ingredients.IngredientClassID, Recipes.RecipeTitle
from Ingredients
Inner join Recipe_Ingredients on Ingredients.IngredientID =
Recipe_Ingredients.IngredientID
Inner join Recipes on Recipe_Ingredients.RecipeID = Recipes.RecipeID;
Link to a DB Fiddle I setup
Diagram of Database:
I think 54 rows is the correct output. My query gave the same number of rows.
FROM Ingredient_Classes ic
LEFT JOIN Ingredients i ON i.IngredientClassID = ic.IngredientClassID
LEFT JOIN Recipe_Ingredients ri ON ri.ingredientId = i.ingredientId
JOIN recipes r ON r.recipeid = ri.recipeId
WHERE i.ingredientId IS NOT NULL
GROUP BY ic.IngredientClassDescription, r.recipetitle
ORDER BY recipetitle;
You can select distinct(recipe.title) and see that all recipes are present in the output. So I don't think we missed anything.

Understand below SQL Query

I need your help to understand below query can anyone help me to describe it, i wanted to know the role of b.id is null and r.id is null in below query if anyone can explain whole code then it would be great?
select l.id as start,
(
select min(a.id) as id
from sequence as a
left outer join sequence as b on a.id = b.id - 1
where b.id is null
and a.id >= l.id
) as end
from sequence as l
left outer join sequence as r on r.id = l.id - 1
where r.id is null;
This query returns your "islands"of your sequence, i.e. start and end of continuos id intervals.
You can read more on gaps and islands here: Special Islands and here The SQL of Gaps and Islands in Sequences
The query is finding islands of consecutive numbers, outputting the start and end of ranges where all consecutive numbers are there, so for the set if numbers
{1,3,4,5,6,9,10}
I would expect
1,1
2,6
9,10
to be selected
The outer query starts by finding number (N) that cannot join to a record holding N-1, detected by r.id is null
The sub query then finds the next highest number (M) that does not join to a record holding M+1 (detected using b.id is null)
so in my example 3 does not have a '2' to join to, meaning 3 begins a range. The first number >= to that with no subsequent record is 6, which has no '7' to make a join to
The query is joining two tables (in this case the same table but it does not matter) using an outer join.
if we have
SELECT t1.a, t1.b, t2.d
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.a = t2.a
WHERE t2.a is null
This means it returns a set of records with all those from table1, however its possible there will not be a joined record from table2 for every record in table1. If there isn't the table2 fields are returned as null so the the WHERE clause is effectively saying return me all records from table1 where we do not have a join record in table2.
In your example where it joins onto itself you are looking where there is not a next/previous record (depending upon which way you are looking at it) based upon the id e.g. if id = 5, then there is not a record with id = 4
Overall the sql as a whole looks like its returning the consecutive id ranges in the sequence table.

RIGHT\LEFT Join does not provide null values without condition

I have two tables one is the lookup table and the other is the data table. The lookup table has columns named cycleid, cycle. The data table has SID, cycleid, cycle. Below is the structure of the tables.
If you check the data table, the SID may have all the cycles and may not have all the cycles. I want to output the SID completed as well as missed cycles.
I right joined the lookup table and retrieved the missing as well as completed cycles. Below is the query I used.
SELECT TOP 1000 [SID]
,s4.[CYCLE]
,s4.[CYCLEID]
FROM [dbo].[data] s3 RIGHT JOIN
[dbo].[lookup_data] s4 ON s3.CYCLEID = s4.CYCLEID
The query is not displaying me the missed values when I query for all the SID's. When I specifically query for a SID with the below query i am getting the correct result including the missed ones.
SELECT TOP 1000 [SID]
,s4.[CYCLE]
,s4.[CYCLEID]
FROM [dbo].[data] s3 RIGHT JOIN [dbo].[lookup_data] s4
ON s3.CYCLEID = s4.CYCLEID
AND s3.SID = 101002
ORDER BY [SID], s4.[CYCLEID]
As I am supplying this query into tableau I cannot provide the sid value in the query. I want to return all the sid's and from tableau I will be do the rest of the things.
The expected output that i need is as shown below.
I wrote a cross join query like below to acheive my expected output
SELECT DISTINCT
tab.CYCLEID
,tab.SID
,d.CYCLE
FROM ( SELECT d.SID
,d.[CYCLE]
,e.CYCLEID
FROM ( SELECT e.sid
,e.CYCLE
FROM [db_temp].[dbo].[Sheet3$] e
) d
CROSS JOIN [db_temp].[dbo].[Sheet4$] e
) tab
LEFT OUTER JOIN [db_temp].[dbo].[Sheet3$] d
ON d.CYCLEID = tab.CYCLEID
AND d.SID = tab.SID
ORDER BY tab.SID
,tab.CYCLEID;
However I am not able to use this query for more scenarios as my data set have nearly 20 to 40 columns and i am having issues when i use the above one.
Is there any way to do this in a simpler manner with only left or right join itself? I want the query to return all the missing values and the completed values for the all the SID's instead of supplying a single sid in the query.
You can create a master table first (combine all SID and CYCLE ID), then right join with the data table
;with ctxMaster as (
select distinct d.SID, l.CYCLE, l.CYCLEID
from lookup_data l
cross join data d
)
select d.SID, m.CYCLE, m.CYCLEID
from ctxMaster m
left join data d on m.SID = d.SID and m.CYCLEID = d.CYCLEID
order by m.SID, m.CYCLEID
Fiddle
Or if you don't want to use common table expression, subquery version:
select d.SID, m.CYCLE, m.CYCLEID
from (select distinct d.SID, l.CYCLE, l.CYCLEID
from lookup_data l
cross join data d) m
left join data d on m.SID = d.SID and m.CYCLEID = d.CYCLEID
order by m.SID, m.CYCLEID

Performance : Left JOIN with IS NULL join condition in SQLite

select *
from Dummy LEFT JOIN data_stream_2
ON ((Dummy.id_2=data_stream_2.id_2) OR
(Dummy.id_2 IS NULL and data_stream_2.id_2 IS NULL))
This query takes 26 seconds. The moment I remove the IS NULL check, i.e
select *
from Dummy LEFT JOIN data_stream_2
ON ((Dummy.id_2=data_stream_2.id_2))
it takes only 1.3 seconds.
How can I make the query faster?
It us similar to this case Slow query with left outer join and is null condition but the difference is in his case join was not really required since he was using only columns from Dummy and not from data_stream_2. I need columns from both.
In the general case, you can separate the two parts of the OR into two parts of a compound query:
SELECT *
FROM Dummy
LEFT JOIN data_stream_2
ON Dummy.id_2 = data_stream_2.id_2
UNION ALL
SELECT *
FROM Dummy
JOIN data_stream_2
ON Dummy.id_2 IS NULL AND data_stream_2.id_2 IS NULL;
However, SQLite's IS operator can use arbitrary expressions on either side, and supports index optimizations, so you can simply use it to compare the IDs:
SELECT *
FROM Dummy
LEFT JOIN data_stream_2
ON Dummy.id_2 IS data_stream_2.id_2;

When a SQL Server query returns no rows(NOT null rows) how do you include that in an aggregate function?

I'm writing a query to look for courses that do not have any of its gradable items graded.
In Blackboard when a user doesn't have a grade at all(e.g. no attempt was ever made) there simply isn't a row in the table gradebook_grade
So if a course doesn't have any grades at all the gradebook_grade table does not have any rows referencing the primary key of the Blackboard course_id
This is what I've used so far:
use bblearn
select cm.course_id
from course_main cm
join gradebook_main gbm on cm.pk1 = gbm.crsmain_pk1
join gradebook_grade gbg on gbm.pk1 = gbg.gradebook_main_pk1
where cm.pk1 = 3947
group by cm.course_id
having count(gbg.pk1) <= 0
The course in question(pk1 3947) is confirmed to not have any grades. So SQL Server says 0 rows affected, naturally.
The thing is, it doesn't select the course_id. I'm guessing having doesn't account for blank/non-existent rows. Is there a way to structure the query to get the course ID when there isn't anything returned? Am I joining on the wrong columns or using where on the wrong column? Any help is appreciated.
Use a left join
select cm.course_id
from course_main cm
left join gradebook_main gbm on cm.pk1 = gbm.crsmain_pk1
left join gradebook_grade gbg on gbm.pk1 = gbg.gradebook_main_pk1
where cm.pk1 = 3947
group by cm.course_id

Resources