How to get table A and count of table B with Linq to Sql group by - linq-to-sql

I have a Linq to SQL query that I want to return select columns from all matching rows from one table (TableC in my simplified query below) and a count of matching rows in another table (TableB in below). Certain other tables need to be involved too for the where clause to work (removed in simplified query).
How do I get the columns I need from TableC and a count of TableB?
This is a simplified version of my query:
var q = from a in dc.TableA
from b in dc.TableB
join c in dc.TableC on b.TableBID equals c.ID
join d in dc.TableD on a.ID equals d.TableAID
where 1 == 1 //lots of interesting stuff here
group c by new { b, c } into g
select new
{
ID = g.Key.c.ID,
Name = g.Key.c.Name,
Count = g.Count()
};
Update: I think I found a solution using group joins - answer posted below. I would still like to know if that was the right solution.

I came up with this solution after reading about Linq group joins.
var q = from a in TableC
join b in (from c in TableB
where (from d in TableA
join f in TableD on d.ID equals f.ID
where 1 == 1 //for simplicity
select d).Any()
&& 1 == 1 //more simplification
select c) on a.TableBID equals b.ID into g
where 1 == 1 //more simplification
select new
{
a.ID,
a.Name,
Count = g.Count()
};

Related

Join table where the id doesn't exist [duplicate]

This question already has answers here:
Return row only if value doesn't exist
(2 answers)
Closed 2 years ago.
I want to do a SELECT that gets the data from a table and also JOINS the information from a table where the d.demographic_category_id from demographic_data doesn't exist in demographic_category column c.demographic_category_id
So it's something like this:
SELECT *
FROM demographic_data d
INNER JOIN demographic_info i
ON d.demographic_info_id = i.demographic_info_id
AND i.student_id = 1
LEFT JOIN demographic_category c
ON d.demographic_category_id
NOT IN ( select c.demographic_category_id from demographic_category c);
What i want to do is to get the demographic_data which is being done correctly with this statement.
SELECT *
FROM demographic_data d
INNER JOIN demographic_info i
ON d.demographic_info_id = i.demographic_info_id
AND i.student_id = 1
BUT THEN grab the data from demographic_category WHERE the demographic_data.demographic_category_id DOESN'T exist IN demographic_category, so therefore grab the categories that doesn't exist in the ids from the query from above this paragraph.
You can use a WHERE clause. I would recommend NOT EXISTS:
SELECT *
FROM demographic_data d JOIN
demographic_info i
ON d.demographic_info_id = i.demographic_info_id AND
i.student_id = 1
WHERE NOT EXISTS (SELECT 1
FROM demographic_category c
WHERE d.demographic_category_id = c.demographic_category_id
);
It seems quite odd to me that you would have a column that doesn't match, however. If you have a foreign key relationship defined, then all the values (except for NULL of course) will match.
EDIT:
Based on your comment, you seem to just want a LEFT JOIN:
SELECT *
FROM demographic_data d JOIN
demographic_info i
ON d.demographic_info_id = i.demographic_info_id AND
i.student_id = 1 LEFT JOIN
demographic_category c
ON d.demographic_category_id = c.demographic_category_id;

correct sql query to simplify relationship (mysql)

I have the following table:
table A
id emp emp_dst
1 a b
2 a d
3 b c
4 b a
5 c d
6 d a
7 d b
8 d c
my sql query should return me the following simplified table since a = b equals b = a
table B
emp emp_dst
a b
a d
b c
d b
d c
but I have no idea how to do this in an sql query in MYSQL,
try revising expressions with UNION but the results are wrong
An alternative that suits my personal preferences better...
(Based on your comment that the id in the results was not relevant.)
SELECT
CASE WHEN emp <= emp_dst THEN emp ELSE emp_dst END AS emp,
CASE WHEN emp <= emp_dst THEN emp_dst ELSE emp END AS emp_dst
FROM
yourTable
GROUP BY
1, 2
ORDER BY
1, 2
If you want an id, then you can add MIN(id). Just note that the id found may actually have the two values the other way around.
An alternative that uses a LEFT JOIN rather than GROUP BY.
SELECT
yourTable.*
FROM
yourTable
LEFT JOIN
yourTable AS reflection
ON reflection.emp_dst = yourTable.emp
AND reflection.emp = yourTable.emp_dst
AND reflection.id <> yourTable.id
WHERE
(reflection.id IS NULL)
OR (yourTable.emp < reflection.emp_dst)
OR (yourTable.emp = reflection.emp_dst AND yourTable.id < reflection.id)
ORDER BY
yourTable.emp,
yourTable.emp_dst
(The last OR is only needed if a table can have 'a', 'a', and it appear twice.)
Note: This may benefit from having two indexes...
CREATE INDEX yourTable_e_ed_id ON yourTable( emp, emp_dst, id );
CREATE INDEX yourTable_ed_e_id ON yourTable( emp_dst, emp, id );

MySQL query with multiple AND operators not working

I'm having a problem with a query:
SELECT l.LookupID, l.companyID, c.companyID, c.companyname, l.selectionID
FROM companies c
INNER JOIN lookup l
ON c.companyID = l.companyID AND c.companyID = 1 AND c.companyID = 2
WHERE l.selectionID = 2 AND l.selectionID = 2
GROUP BY l.LookupID
Obviously the AND doesn't return the result expected. The result I'm expecting is that both selectionID 2 and 4 must exist in companyID 1 and 2.
I was thinking about using Count(*) but I'm very confused.
There are absolutely zero rows in c where this condition will be TRUE. (If one of these conditions is true, the other is guaranteed to be false.)
c.companyID = 1 AND c.companyID = 2
Without a sample of example data and an expected result, the specification is not clear. There are several interpretations. and those interpretations can differ in significant ways. So that means any answer to the question is just a "guess".
Here's an example of returning rows from company where there are matching rows in lookup for both selectionID 2 and 4.
SELECT c.companyID
, c.companyname
FROM companies c
JOIN ( SELECT l.companyID
FROM lookup l
WHERE l.companyID IN (1,2)
AND l.selectionID IN (2,4)
GROUP BY l.companyID
HAVING COUNT(DISTINCT l.selectionID) = 2
) d
ON d.companyID = c.companyID
ORDER BY c.companyID
That's just an example of how we might return a particular result. Again, without a more definitive specification (example data, expected output), we're just guessing.
There are other query patterns that will return an equivalent result. e.g.
SELECT c.companyID
, c.companyname
FROM companies c
WHERE c.companyID in (1,2)
AND EXISTS ( SELECT 1
FROM lookup l2
WHERE l2.companyID = c.companyID
AND l2.selectionID = 2
)
AND EXISTS ( SELECT 1
FROM lookup l4
WHERE l4.companyID = c.companyID
AND l4.selectionID = 4
)
ORDER BY c.companyID

SQL query to select from two tables and return if a value exists

i have two tables:
callcosts
callcosts_custom
is there a way i can select from both tables and return the value of cost from callcosts_custom if the row exists and if it doesnt exist, return the column price from callcosts
with the following WHERE clause:
WHERE callcosts_custom.parent = callcosts.sequence
basically, the callcosts table has all of the default data in and custom data can be added per customer.
the relationship is as follows:
call_costs.sequence = callcosts_custom.parent
so i want to check if a row exists in callcosts_custom for a specific callcosts_custom.customer. if it does, it will return callcosts_custom.cost and if it does not exist to return callcosts_price
updated query:
select b.cost
from call_costs_custom b
where a.sequence = b.parent AND b.customer_seq = '124'
union all
select a.retail
from call_costs a
where a.sequence = '4706' and
not exists (select 1 from call_costs_custom b where b.parent = a.sequence);
Yes . . . this sounds like a prioritization query. This typically looks like
select ccc.price
from callcosts_custom ccc
where ccc.?? = ??
union all
select cc.price
from callcosts ccc
where cc.?? = ?? and
not exists (select 1 from callcosts_custom ccc where ccc.?? = cc.??);
It is unclear from your question what the columns are.
This can be done by left joining the tables (under the assumption that every row must exist in callcosts and may or may not exist in callcosts_custom, but not the other way round) and using coalesce. You haven't given too much information about the tables, but I'm assuming there's some ID column to identify the rows:
SELECT c.id, COALESCE(cc.price, c.price) AS price
FROM callcosts c
LEFT JOIN callcosts_custom cc ON c.id = cc.id
This should work for you:
SELECT IFNULL(cc.cost, c.price) cost
FROM callcosts c
LEFT JOIN cc.parent = c.sequence

Where clause in Query

My query looks like this. Suppose it was run well.im confused the last part of the Where clause.Can i write that from two different table?..how can i write it, cause i want to display those staff who a Active from that date range.
select d.Division,a.FirstName,
(select count(h.id) from Department h
inner join institution i on d.institution_id = i_Id
----
----
where i.institution_id =d.Id and h. date between #startDate and #endDate) as test
from Division d, inmate a
where d.Active = 1 and a.Active = 1
edited
i have edit my query and the final looks like this..
select d.DivisionName,a.FirstName, (select count(h.id) from InHistory h inner join Institution i on h.Institution_id = i.Id inner join InType it on h.InType_id = it.Id inner join mate a on h.mate_id = a.Id where i.InstitutionRegion_id = d.Id and it.InTypeName like '%Staff%' and h.AdmissionDate between '18/02/2013' and '18/02/2013') as Admission from Division d, mate a where d.Active= 1 and a.Active =1
Yes, you can give comparison between any number of tables in where clause provided you are giving valid conditions inside your where clause. I think you should refer SQL JOINS
You can add as many as you want clauses inside the WHERE from your SQL query..
see an example
SELECT *
FROM employee inner join department on
employee.DepartmentID = department.DepartmentID;
WHERE
employee.active = TRUE AND
department.group = 3
http://en.wikipedia.org/wiki/Join_(SQL)#Inner_join