Linq to sql left join and group by - linq-to-sql

I have 2 tables
table1
ID Name
1 name1
2 name2
3 name3
4 name4
table2
ID Description Status
1 desc1 1
1 desc2 1
2 desc3 1
3 desc4 0
I need to get list of items {ID, Name} which are not in second table or are all stopped in second table. This items should be grouped.
in this example I should get
{1, name1},
{2, name2},
{4, name4}.

I believe this should get what you want:
var result = from p in table1
where table2.Any(x => x.ID == p.ID) == false
|| table2.Any(x => x.ID == p.ID && x.Status == 1)
select p;

Related

How to write a query for selecting from three tables and if the values are null should not select?

I have three tables
1) Category_master
CID CTYPE
---------------------
1 2
--------------------
2 2
--------------------
3 1
-------------------
4 3
----------------
5 2
-------------------
6 3
2) NSS_maste
NID MID Name Value
1 5 Red 86
2 1 Blue 96
3) Sports_master
SID MID Name Cat
1 4 Walk Leg
The above is my table
I have to select CTYPE, NSS.NAME NSS.value,sports.name, sports.cat from category master,NSS_master and sports_master an it should not select null value Eg: for CID 2 there is no value in NSS_master table so it should not select but for CID 3 CTYPE 1 select name and other values as null
How to implement this thank you
Use Inner Join to avoid null values:
SELECT C.CTYPE, N.NAME, N.value, S.name, S.cat
FROM Category_Master C Inner Join NSS_master N ON C.CID = N.MID
Inner Join Sports_Master S ON C.CID = S.MID

MySQL group by descending order

I have a table that does not contain a unique column
id | fid | ver | dir
1 || 1 || 1 || 3
2 || 2 || 1 || 2
3 || 3 || 1 || 3
4 || 3 || 2 || 3
5 || 4 || 1 || 4
6 || 5 || 1 || 5
My question is how can I select the ID of latest fid (based from ver) in dir = 3
I tried (SELECTidFROMtableWHEREdir='3' GROUP BYfidORDER BYversion) but it gives me
id
1
3
which is not the result I want to get. Here is the result I expect to have:
id
1
4
select id
from myTable t1
where dir = 3
and not exists (
select 1
from myTable t2
where t1.version < t2.version
and t1.dir = t2.dir
and t1.fid = t2.fid
)
order by version
SELECT MAX(id) FROM table WHERE dir = '3' GROUP BY fid ORDER BY version
Try group by Version instead,
SELECT id FROM table WHERE dir='3' GROUP BY version

Attempting to join and group data

I have two tables. The first is property and the second is category
The structure of the property table is:
id propertyname
1 a
2 b
3 c
4 d
and the structure of category is:
id propid catid
1 1 2
2 1 3
3 2 1
4 3 1
5 3 2
6 4 3
I'm trying to create a result like this:
id propertyname propid catid
1 a 1 2,3
2 b 2 1
3 c 3 1,2
4 d 4 3
How can I get this result? I used a group by clause and group_concate() function but it doesn't seem to work.
Here is what I've tried:
SELECT prop.*,category.property_id cat_prop,category.type_id type
FROM tbl_property prop,
tbl_category_type category
WHERE prop.id=category.property_id
Try this:
SELECT t0.id, t0.propertyname, group_concat(t1.catid)
FROM t0
INNER JOIN t1 ON t0.id = T1.propid
GROUP BY id
That should give you your result

Use sequential CASEs as parameters for larger CASE

SELECT CASE
WHEN
CASE
WHEN `AA`>6
THEN `A`
ELSE NULL
END,
CASE
WHEN `BB`>6
THEN `B`
ELSE NULL
END,
CASE
WHEN `CC`>6
THEN `C`
ELSE NULL
END
THEN `NAME`
END
FROM TABLE;
The goal of this query is to show the columns A through C and Name. but if A-C is null to not show NAME.
I'm new to CASEs and 'advanced' queries in general, so if I have this set up like a fool, feel free to let me know.
Thanks for reading.
NOTE: doesn't compile
The logic I'm trying to get is so:
if(
if(AA>6) then 1 else 0
OR
if(BB>6) then 1 else 0
OR
if(CC>6) then 1 else 0
etc,etc
) then 1 else 0
Table:
Name A B C AA BB cc
--------------------------------------------------------
Name1 Data1 null Data3 3 n 15
Name2 null Data2 Data4 n 2 8
Name3 null Data2 Data4 n 2 2
Output wanted if it's only showing values gt 6:
Name A B C
-------------------------
Name1 Data3
Name2 Data4
One way to do it
SELECT Name,
CASE WHEN aa > 6 THEN a END a,
CASE WHEN bb > 6 THEN b END b,
CASE WHEN cc > 6 THEN c END c
FROM table1
WHERE aa > 6
OR bb > 6
OR cc > 6
or
SELECT Name,
CASE WHEN aa > 6 THEN a END a,
CASE WHEN bb > 6 THEN b END b,
CASE WHEN cc > 6 THEN c END c
FROM table1
HAVING COALESCE(a, b, c, -1) <> -1
In the second query -1 is just a constant that will be returned if all of your columns have NULL values. You can use any value that will never be a part of your result set. In this particular case since you're applying column > 6 condition to every column you can use any number that is less than 6.
Output:
| NAME | A | B | C |
-----------------------------------
| Name1 | (null) | (null) | Data3 |
| Name2 | (null) | (null) | Data4 |
Here is SQLFiddle demo

how to get sum of two tables linked to a third

would any sql Wizards out there help with with this question:
suppose I have 3 tables:
tbltype tblvalue tblcost
id | type id | val | typeid id | cost| typeid
---------- ------------------ ------------------
1 | aaa 1 | 3 | 1 1 | 5 | 1
2 | bbb 2 | 2 | 1 2 | 3 | 1
3 | 2 | 2 3 | 1 | 2
4 | 1 | 2 4 | 4 | 2
When I run this query:
SELECT t.type, SUM(val), SUM(cost)
FROM
tbltype t
LEFT JOIN tblcost c ON (c.typeid = t.id)
LEFT JOIN tblvalue v ON (v.typeid = t.id)
GROUP BY t.type;
I get the wrong value of
type | SUM(val) | SUM(cost)
---------------------------
aaa | 10 | 16
bbb | 6 | 10
how do I get the right value of:
type | SUM(val) | SUM(cost)
---------------------------
aaa | 5 | 8
bbb | 3 | 5
and why does sql behaves like that?
To see why, take the group and sums out of your query and look at what it's summing:
SELECT t.type, val, cost
FROM
tbltype t
LEFT JOIN tblcost c ON (c.typeid = t.id)
LEFT JOIN tblvalue v ON (v.typeid = t.id)
You'll see you have each possible combination of the rows from tblcost and tblvalue in the output-- this means some of them get counted multiple times when you sum them.
You need to aggregate tblcost and tblvalue separately. You can then join them back onto tbltype. Gavin's answer already shows one way to do that. Another way is:
SELECT t.type, COALESCE(cost, 0) AS cost, COALESCE(val, 0) AS val
FROM tbltype t
LEFT JOIN (SELECT SUM(cost) AS cost, typeid FROM tblcost GROUP BY typeid) tc
ON tc.typeid = t.id
LEFT JOIN (SELECT SUM(val) AS val, typeid FROM tblvalue GROUP BY typeid) tv
ON tv.typeid = t.id
... which may or may not perform differently (and may or may not be better) depending on which database engine you're actually using.
SELECT t.type,
COALESCE((SELECT SUM(v.val) FROM tblvalue AS v WHERE v.typeid = t.id),0) AS val,
COALESCE((SELECT SUM(c.cost) FROM tblcost AS c WHERE c.typeid = t.id),0) AS cost
FROM tbltype AS t;
I think you've got enough answers suggesting how to solve your problem correctly. You've also got #araqnid's answer that helps you to see why you get such results in the end. The only thing that remains for me seems to be to explain the behaviour itself, as per your request.
Basically, the reason behind such behaviour is the fact that the second join is performed not on tbltype and tblvalue, as one might think, but on the result of the join between tbltype and tblcost, on the one hand, and the tblvalue table, on the other. Now, the first join produces duplicates of t.id, because they match the second table more than once:
tbltype tblcost
id type id cost typeid t.id t.type c.id c.cost c.typeid
-- ---- × -- ---- ------ = ---- ------ ---- ------ --------
1 aaa 1 5 1 1 aaa 1 5 1
1 bbb 2 3 1 1 aaa 2 3 1
3 1 2 2 bbb 3 1 2
4 4 2 2 bbb 4 4 2
The second join produces more duplicates, because:
every occurrence of t.id from the first join's result set is getting matched against v.typeid
and
the typeid values in the tblvalue table are duplicated too.
As a result, rows from both tblcost and tblvalue get duplicated in the process:
tblvalue
t.id t.type c.id c.cost c.typeid id val typeid
---- ------ ---- ------ -------- -- --- ------
1 aaa 1 5 1 × 1 3 1 =
1 aaa 2 3 1 2 2 1
2 bbb 3 1 2 3 2 2
2 bbb 4 4 2 4 1 2
t.id t.type c.id c.cost c.typeid v.id v.val v.typeid
---- ------ ---- ------ -------- ---- ----- --------
1 aaa 1 5 1 1 3 1
1 aaa 1 5 1 2 2 1
= 1 aaa 2 3 1 1 3 1
1 aaa 2 3 1 2 2 1
2 bbb 3 1 2 3 2 2
2 bbb 3 1 2 4 1 2
2 bbb 4 4 2 3 2 2
2 bbb 4 4 2 4 1 2
The only way out for you seems to be to aggregate each table separately. That doesn't necessarily imply separate queries, just separate subqueries, as you can now see from the answers.
QUickest solution is to split the query in two
SELECT
`tbltype`.`type`, SUM(val)
FROM
tbltype
LEFT JOIN `tblvalue` ON (`tblvalue`.`typeid` = `tbltype`.`id`)
GROUP BY `tbltype`.`type`;
and
SELECT
`tbltype`.`type`, SUM(cost)
FROM
tbltype
LEFT JOIN `tblcost` ON (`tblcost`.`typeid` = `tbltype`.`id`)
GROUP BY `tbltype`.`type`;
Something like this:
select t1.id, val, cost from (
select t.id, sum(val) as val
from tbltype t
join tblvalue v on t.id = v.typeId
group by t.id
) t1
join (
select t.id, sum(cost) as cost
from tbltype t
inner join tblcost c on t.id = c.typeid
group by t.id
) t2 on t1.id = t2.id
... or if tblcost and tblvalue are related by id:
select t.id, sum(val) as val, sum(cost) as cost
from tbltype t
inner join tblcost c on t.id = c.typeid
inner join tblvalue v on c.id = v.id
group by t.id