How to write linq query for this case? - silverlight-4.0

Suppose I have 3 tables:
TabA(id1, ...., id2, ...)
TabB(id2, ...)
TabC(id3, ...., id2, ...)
now what I want is to find out all records in TabC, those records should be able to be identified from TabA by its id1. If use SQL, the query would be
Select c.*
from TabC c
join TabB b on c.id2 = b.id2
join TabA a on a.id2 = b.id2
Where id1 = inputID
How to write this linq like when I use EF and WCF Ria Service for SL app?
this.ObjectContext.TabC.Where(.....

I normaly do it this way(I find it easier to read):
var q =
from c in ctx.TabC
from b in ctx.TabB.Where(b=> b.id2 == c.id2)
from a in ctx.TabA.Where(a=> a.id2 == b.id2)
where a.id1 == inputID
select new {....};
I hope this helps!

Related

Index on join and where

Given the next SQL statement:
Select *
from A join B
on A.id1=B.id1 and
A.id2=B.id2
where A.year=2016
and B.year=2016
and knowing table A is much smaller than table B, so I need the database first to access A table by year, then join, then filter B table by year, my question is:
does it make sense to create an index over B like (id1,id2,year) for improve performance?
Many thanks!
For this query:
Select *
from A join
B
on A.id1 = B.id1 and A.id2 = B.id2
where A.year = 2016 and B.year = 2016;
I would suggest indexes on A(year, id1, id2) and B(id1, id2, year).
You might also write the query as:
Select *
from A join
B
on A.id1 = B.id1 and A.id2 = B.id2 and A.year = B.year
where A.year = 2016;
The answer to your question is "yes" and index on B is the right thing to do. In this version, the order of the columns in the index does not really matter.

Join WHERE clause - table has row with defined value, or no entry

Can anyone help me figure out the correct WHERE clause for the following scenario:
select A.name
from tableA A, tableB B
where A.id = B.id
and
(
B.field = 5
OR
B.hasNoRowForJoinedID
)
I feel like I'm missing something really obvious here in how to accomplish this, but I can't for the life of me put my finger on it.
You are using an outdated SQL Syntax. To perform the LEFT OUTER JOIN based your your request above, you can do the following:
SELECT A.name
FROM A
LEFT OUTER JOIN B ON A.id = B.id
WHERE (B.field = 5 OR B.field IS NULL)
Use proper join syntax and not the outdated ones:
select A.name
from tableA A
left join tableB B on A.id = B.id and B.field = 5

INNER JOIN where **every** row must match the WHERE clause?

Here's a simplified example of what I'm trying to do. I have two tables, A and B.
A B
----- -----
id id
name a_id
value
I want to select only the rows from A where ALL the values of the rows from B match a where clause. Something like:
SELECT * from A INNER JOIN B on B.a_id = A.id WHERE B.value > 2
The problem with the above query is that if ANY row from B has a value > 2 I'll get the corresponding row from A, and I only want the row from A if
1.) ALL the rows in B for B.a_id = A.id match the WHERE, OR
2.) There are no rows in B that reference A
B is basically a table of filters.
SELECT *
FROM a
WHERE NOT EXISTS
(
SELECT NULL
FROM b
WHERE b.a_id = a.a_id
AND (b.value <= 2 OR b.value IS NULL)
)
This should solve your problem:
SELECT *
FROM a
WHERE NOT EXISTS (SELECT *
FROM b
WHERE b.a_id = a.id
AND b.value <= 2)
Here is the way in which this is obtained.
Suppose that we have available a universal quantifier (parallel to EXISTS, the existential quantifier), with a syntax like:
FORALL table WHERE condition1 : condition2
(to be read: FORALL the elements of table that satisfy the condition1, then condition2 is true)
So you could write your query in this way:
SELECT *
FROM a
WHERE FORALL b WHERE b.a_id = a.id : b.value > 2
(Note that forall is true even when no element in b exists with a value of a.id)
Then we can transform the universal quantifier in the existential one, with a double negation, as usual:
SELECT *
FROM a
WHERE NOT EXISTS b WHERE b.a_id = a.id : NOT (b.value > 2)
In plain SQL this can be written as:
SELECT *
FROM a
WHERE NOT EXISTS (SELECT *
FROM b
WHERE b.a_id = a.id
AND (b.value > 2) IS NOT TRUE)
This technique is very handy in case of universal quantification.
Answering this question (which it seems you actually meant to ask):
Return all rows from A, where all rows in B with B.a_id = A.id also pass the test B.value > 2.
Which is equivalent to:
Return all rows from A, where no row in B with B.a_id = A.id fails the test B.value > 2.
SELECT a.* -- "rows from A" (so don't include other columns)
FROM a
LEFT JOIN b ON b.a_id = a.id
AND (b.value > 2) IS NOT TRUE -- safe inversion of logic
WHERE b.a_id IS NULL;
When inverting a WHERE condition carefully consider NULL. IS NOT TRUE is the simple and safe way to perfectly invert a WHERE condition. The alternative would be (b.value <= 2 OR b.value IS NULL) which is longer but may be faster (easier to support with index).
Select rows which are not present in other table
Try this
SELECT * FROM A
LEFT JOIN B ON B.a_id = A.id
WHERE B.value > 2 OR B.a_id IS NULL
SELECT * FROM A LEFT JOIN B ON b.a_id = a.id
WHERE B.a_id IS NULL OR NOT EXIST (
SELECT 1
FROM b
WHERE b.value <= 2)
SELECT a.is, a.name, c.id as B_id, c.value from A
INNER JOIN (Select b.id, b.a_id, b.value from B WHERE B.value > 2) C
on C.a_id = A.id
Note it is a poor practice to use select *. You shoudl only specify fields you need. IN this case, I might possibly remove the b.Id refernces becasue they are probably not needed. If you have a join there is a 100% chance you are wasting resouces sending data you don't need becasue the join fields will be repeated. That is why I did nto include a_id in the final result set.
If you prefer not to use EXISTS, you can use an outer join.
SELECT A.*
FROM
A
LEFT JOIN B ON
B.a_id = A.id
AND B.value <= 2 -- note: condition reversed!!
WHERE B.id IS NULL
This works by searching for the existence of a failing record in B. If it finds one, then the join will match, and the final WHERE clause will exclude that record.

How to find if LEFT JOIN joined an actual row, or placeholder NULL values?

Suppose I issue a query like this:
SELECT a.x, b.y FROM a LEFT JOIN b ON b.id = a.id
I also want to know if a row from b is actually joined or there are just placeholder NULL values supplied by LEFTJOIN. I guess I can determine it comparing values of a.id and b.id in the result, but is there a way to do this in the query itself?
I.e. I'd want something like
SELECT a.x, b.y, b_is_actually_joined FROM a LEFT JOIN b ON b.id = a.id
where values in the column b_is_actually_joined are 1 or 0 (for example).
Just check for NULL b.id:
SELECT a.x, b.y, b.id IS NOT NULL AS b_is_actually_joined
FROM a
LEFT JOIN b ON b.id = a.id
For Oracle SQL you can use NVL2 function:
SELECT a.id, b.*, NVL2(b.id, 1, 0) AS b_is_actually_joined
FROM a
LEFT JOIN b ON b.id = a.id
SQL Fiddle
This should work in Ms Sql Server:
select CAST((coalesce(b.id, 0)) as bit) as b_is_actually_joined FROM a
LEFT JOIN b ON b.id = a.id
I am unaware of a standard SQL solution for this

Join results in 3 tables to my existing query containing 2 tables

Hopefully someone can show me how to complete my sql. I'll start by showing you my existing query:
Select a.ID, a.NAME,
CASE When b.SOURCE = Value1 then 'Rename1'
When b.SOURCE = Value2 then 'Rename2'
When b.SOURCE = etc. ....
END,
b.TARGET, b.COMPARE
FROM Table'a', Table'b'
WHERE b.SOURCE in(Value1, Value2, Value...etc)
AND (a.ID = b.ID_1 or a.ID = b.ID_2)
Now my issue is my client wants to look up 3 different tables (each table contains primary key = a.ID) and return the values from only the column values that are referenced in the Case Statement above.
I assume I would need to do a join but not sure how to go about it. Any suggestions?
Thanks!
Puckhog
Following is the sample query:
Select T1.column,T2.Column,T3.Column
From Table1 T1
Join Table2 T2
on T1.MatchingColumn=T2.MatchingColumn
Join Table3 T3
on T2.MatchingColumn=T3.MatchingColumn
You could do something like this?
SELECT
a.ID, a.NAME, c.SOMETHING
FROM
a
JOIN
b
ON a.ID = b.ID
JOIN
c
ON a.ID = c.ID
WHERE [conditions]