Querying tables with count from other tables - sql-server

I have three tables in database that are "UserGroup" which has a unique group for user. The second table is "Users" that has users but multiple users can belong to same usergroup.
Similarly I have a third table "Roles" that contains roles and multiple roles
can belong to same "usergroup".
Therefore parent table is UserGroup the id of this table is foreign key in two other tables.
A related question has been already asked here but if you can answer with my scenario , it would be better
Select from one table with count from two other tables
I am trying to query these tables such that I need count of "user Group" from
each of the two tables i.e from "users" and roles". If you can help with the Linq query, it would be appreciated.
For example:
"User Group Table"
Id GroupName
1 Admin
2 IT
3 Helpdesk
"Users Table"
Id USerGroupId UserName
1 1 Tom
2 1 Mickey
3 2 John
4 3 Sandy
"Roles Table"
Id USerGroupId Role
1 2 Supervisor
2 2 Superidetendent
3 3 etc
4 3 etc
Output should show:
GroupName USerCount RolesCount
Admin 2 0
IT 1 2
Helpdesk 1 2

SELECT GroupName
,(SELECT COUNT*) FROM Users U WHERE U.USerGroupId=G.Id) [USerCount]
,(SELECT COUNT*) FROM Roles r WHERE R.USerGroupId=G.Id) [RolesCount]
FROM Group g

I think something like that should work:
UsersTable.GroupBy(u => u.USerGroupId).Select(group => new {
USerGroupId = group.Key,
Count = group.Count()
}).OrderBy(x => x.USerGroupId);
RolesTable.GroupBy(u => u.USerGroupId).Select(group => new {
USerGroupId = group.Key,
Count = group.Count()
}).OrderBy(x => x.USerGroupId);

This is the linq to Entity in c# (if you use Entity Framework to connect to DB)
var query =
from h in (
(from b in db.UserTable
group b.UserGroup by new {
b.UserGroup.GroupName
} into g
select new {
g.Key.GroupName,
UserCount = g.Count(p => p.GroupName != null)
}))
join k in (
(from d in db.Roles
group d.UserGroup by new {
d.UserGroup.GroupName
} into g
select new {
g.Key.GroupName,
RolesCount = g.Count(p => p.GroupName != null)
})) on h.GroupName equals k.GroupName into k_join
from k in k_join.DefaultIfEmpty()
select new {
h.GroupName,
h.UserCount,
RolesCount = k.RolesCount
};
this is linq to SQL in c# (if you use DBML)
var query =
from h in (
(from a in db.UserGroup
join b in db.UserTable on new { Id = a.Id } equals new { Id = b.UserGroupId } into b_join
from b in b_join.DefaultIfEmpty()
group a by new {
a.GroupName
} into g
select new {
g.Key.GroupName,
UserCount = g.Count(p => p.GroupName != null)
}))
join k in (
(from d in db.Roles
group d.UserGroup by new {
d.UserGroup.GroupName
} into g
select new {
g.Key.GroupName,
RolesCount = g.Count(p => p.GroupName != null)
})) on h.GroupName equals k.GroupName into k_join
from k in k_join.DefaultIfEmpty()
select new {
h.GroupName,
h.UserCount,
RolesCount = k.RolesCount
};
this is the source SQL
SELECT h.GroupName, h.UserCount, k.RolesCount
FROM
(SELECT a.GroupName, count(a.GroupName) as UserCount
from UserGroup a
LEFT JOIN UserTable b on a.id = b.UserGroupId
group by a.GroupName) h
LEFT JOIN (
SELECT a.GroupName, count(a.GroupName) as RolesCount
from UserGroup a
INNER JOIN Roles d on a.id = d.UserGroupId
group by a.GroupName) k on h.GroupName = k.GroupName

Related

need to convert posted sql query to LINQ

How do i make that query in linq please advise
select *
from tblPermission
where RoleId in (select roleid from tbluserrole where userid = #userID)
When converting from SQL to LINQ, convert in the order of the LINQ phrases. If your SQL has table aliases, use them as the range variables. If a query contains a sub-query, translate it first in the same way. Translate IN into Contains.
var roles = from ur in tbluserrole where ur.userid == parmUserId select ur.RoleId;
var ans = from p in tblPermission
where roles.Contains(p.RoleId)
select p;
You can do this in 2 ways:
var roles = tbluserrole.Where(e => e.userid == userId).Select(e => e.roleid).ToList();
var prmsns = tblPermission.Where(e => roles.Contains(e.RoleId).ToList()
or
var prmsns = (from e in tblPermission
let roles = tbluserrole.Where(f => f.userid == userId).Select(f =>
f.roleid).ToList();
where roles.Contains(e.RoleId)
select e).ToList();
from
EDIT:
you can do this with inner join like this
var prmsns = (from e in tblPermission
join f in tbluserrole on tblPermission.RoleId equals tbluserrole.roleid
where f.userId == userId
select e).ToList();

SQL server 2012 - Query on retrieving matching records from a table by cross checking with two other tables

I have three tables (say A,B and C) with same column names and datatype. And these tables can be joined using four unique columns, say name,company,Seq_Number and role. Now I want to select records of particular role from table A and cross check them with the records in Table B and C.If they do not exist in both the tables, then we need to deactivate/remove those records from Table A. The problem is, the records which does not exist in table B might exist in Table C. So, I need to remove the records of particular role only if they don't exist in both B & C tables. I tried with the below query. But it is not returning the expected result. Kindly help me on this
SELECT DISTINCT FAT_Cust.name
, FAT_Cust.Company
, FAT_Cust.role
, FAT_Cust.Seq_Number
, Cust.name
, Cus.Company
, Cust.role
, Cust.Seq_Numberfrom (
SELECT DISTINCT ALC.NAME, ALC.Company, ALC.ROLE, ALC.Seq_Number
FROM AL_Customer ALC
INNER JOIN BL_Customer LPC ON ALC.NAME = LPC.NAME
AND ALC.Company = LPC.Company
AND ALC.ROLE = LPC.ROLE
AND ALC.Seq_Number = LPC.Seq_Number
AND ALC.Record_Active = 1
UNION SELECT DISTINCT ALC.NAME, ALC.Company, ALC.ROLE, ALC.Seq_Number
FROM AL_Customer ALC
INNER JOIN CL_Customer CLC ON ALC.NAME = CLC.NAME
AND ALC.Company = CLC.Company
AND ALC.ROLE = CLC.ROLE AND ALC.Seq_Number = CLC.Seq_Number
AND ALC.Record_Active = 1
) Cust
RIGHT OUTER JOIN AL_Customer FAT_Cust ON FAT_Cust.NAME = Cust.NAME
AND FAT_Cust.Company = Cust.Company
AND FAT_Cust.ROLE = Cust.ROLE
AND FAT_Cust.Seq_Number = Cust.Seq_Number
AND FAT_Cust.Record_Active = 1
WHERE Cust.NAME IS NULL
AND Cust.Company IS NULL
AND Cust.ROLE IS NULL
AND Cust.Seq_Number IS NULL
AND Cust.ROLE < > 'OWN'
Please try the query given below
SELECT ALC.* FROM AL_Customer ALC
LEFT JOIN BL_Customer BPC ON ALC.NAME = BPC.NAME
AND ALC.Company = BPC.Company
AND ALC.ROLE = BPC.ROLE
AND ALC.Seq_Number = BPC.Seq_Number
AND ALC.Record_Active = 1
AND BLC.Record_Active = 1
LEFT JOIN CL_Customer CPC ON ALC.NAME = CPC.NAME
AND ALC.Company = CPC.Company
AND ALC.ROLE = CPC.ROLE
AND ALC.Seq_Number = CPC.Seq_Number
AND ALC.Record_Active = 1
AND CLC.Record_Active = 1
WHERE ALC.Record_Active = 1
AND (BPC.NAME IS NULL)
AND (CPC.NAME IS NULL)
you can add more condition is where class to narrow down the matching criteria. the above query is assuming that name is present for all the records in the table. I hope this will resolve your issue.

Can I apply join on four tables or anything similar in Entity Framework?

I have four tables
Users
{
PK: UserId
...
}
Products
{
PK: ProductId
FK: UserId
...
}
ProductTags
{
PK: ProductTagId
FK: ProductId
...
}
LikedProducts
{
PK: Id
UserId
ProductId
...
}
Here is my query.
int userId = 1; //It will be different for different user.
var tblProductList = (from t in repo.ProductTags
join p in repo.Products on t.ProductId equals p.ProductId
join u in repo.LikedProducts on p.UserId equals u.UserId
join l in repo.LikedProducts on new { p.ProductId, userId } equals new { l.ProductId, l.UserId }
where productIdList.Contains(p.ProductId)
select p
).ToList();
I am getting The type of once reference in join clause is incorrect error.
I am getting list of ProductId let's say productListIds from azure search. My question is, Is it possible to get some column(Not all data) from each table using single query either by Join or using Entity Framework.
I googled It but didn't find any solution in which we could apply Join more than 3 tables.
Thanks in advance.
I am still unsure as to what you are trying to extract. Here is a corrected query though as you were using LikedProducts twice which is not necessary.
This would get a list of products that the user likes and products that have a tag (through the inner join):
var tblProductListOfLikedProductsForUser = (from p in repo.Products
join tag in repo.ProductTags on p.ProductId equals tag.ProductId // as you are not retrieving tag info this is only usefull if you want to ensure that each product has a tag
join l in repo.LikedProducts on new { p.ProductId, userId } equals new { l.ProductId, l.UserId } // limits products to those the user likes
// join u in repo.Users on l.UserId equals u.UserId // no benifit in using Users if you dont want user info and already have a userid
where productIdList.Contains(p.ProductId)
select p).ToList();
If productId and UserId data exist than return true otherwise false).
Here is a modified query that would return a list of product ids for those that the user likes and are in the list. The joins would only ensure that the product exists in all the tables (i have no idea what the referential integrity is of the db, if there are FK constraints defined you can get rid of the join on products).
var productIdsLikedProductsForUser = (from p in repo.Products // ensure the product exists
join tag in repo.ProductTags on p.ProductId equals tag.ProductId // ensure the product has a tag
join l in repo.LikedProducts on new { p.ProductId, userId } equals new { l.ProductId, l.UserId } // limits products to those the user likes
where productIdList.Contains(l.ProductId)
select l.ProductId).ToList();
If you do not care about that then you do not need a complex join, just query the LikedProducts table directly.
var productIdsLikedProductsForUser = (from l in repo.LikedProducts
where productIdList.Contains(l.ProductId)
&& l.UserId == userId
select l.ProductId).ToList();
As Products table contains UserId(FK reference of Users table) so Is it possible to include UserName, FirstName, LastName from Users Table?
Yes, you can use a group by clause.
var userWithLikedProducts = (from l in repo.LikedProducts
join u in repo.Users on l.UserId equals u.UserId
where productIdList.Contains(l.ProductId)
&& l.UserId == userId
group l.ProductId by new { u.UserName, u.FirstName, u.LastName } into productGroup
select new { User = productGroup.Key, LikedProductIds = productGroup.Select(x => x) }).SingleOrDefault();

SQL query converted to LINQ

How do I write this SQL query using LINQ?
I tried a few ideas but can't figure it out :
SELECT id , Email
FROM Customer
WHERE Customer.Id IN
(SELECT CustPeople.PeopleID
FROM CustPeople WHERE MemID = 1)
Table Customer:
Id Email
--------------------------
1 johnDoe#aol.com
12 billGates#yahoo.com
11 charlieParker#aol.com
Table CustPeople:
Id MemID PeopleID
----------------------
1 1 11
2 1 12
3 4 163
Result :
11 charlieParker#aol.com
12 billGates#yahoo.com
Do I use joins? Is there some way of creating a sub query in linq?
var people = from c in _custRepository.Table
join p in _custPeopleRepository.Table on c.Id equals p.MemID
???
Contains call on a collection will be translated into IN clause:
var people = from c in _custRepository.Table
where _custPeopleRepository.Table
.Where(x => x.MemID == 1)
.Select(x => x.PeopleID)
.Contains(c.Id)
select new { c.Id, c.Email };

Grouping by ShopName Count Different type of Customer(membership)

We have a 2 tables
Table 1
Shop where we have shop details
ShopNo, ShopName
Table 2
Customer where we have all customer details
CustomerId, CustomerName, MembershipType, ShopId
what we are trying to query is
ShopName SilverMember GoldMember LifeMember
ABC 45 110 1
XYZ 90 0 10
DEF 10 10 7
Is there a way to make it possible
if in Linq well and good else only sql query will do thanks in advance
Regards
Moksha
Something like this should do the trick:
select s.ShopName,
count(c1.CustomerId) as 'SilverMember',
count(c2.CustomerId) as 'GoldMember',
count(c3.CustomerId) as 'LifeMember'
from Shop s
left outer join Customer c1 on c1.ShopId = s.ShopNo and c1.MembershipType = 'SilverMember'
left outer join Customer c2 on c2.ShopId = s.ShopNo and c2.MembershipType = 'GoldMember'
left outer join Customer c3 on c3.ShopId = s.ShopNo and c3.MembershipType = 'LifeMember'
group by s.ShopName
Assuming MembershipType contains the actual VARCHAR values SilverMember, GoldMember, and LifeMember, this should work in T-SQL:
SELECT
[ShopName], COUNT([SilverMember]) AS [SilverMember], COUNT([GoldMember]) AS [GoldMember], COUNT([LifeMember]) AS [LifeMember]
FROM
[Table1]
INNER JOIN [Table2]
ON [Table1].[ShopNo] = [Table2].[ShopId]
PIVOT
(
MAX([MembershipType])
FOR [MembershipType] IN ([SilverMember], [GoldMember], [LifeMember])
) AS [P]
GROUP BY
[ShopName]
Example on SQL Fiddle
If you want to use linq:
var query = from s in context.Shops
join c in context.Customers on s.ShopNo equals c.ShopId
group c by s.ShopName into g
select new
{
ShopName = g.Key,
SilverMember = g.Count(c => c.MembershipType == "SilverMember"),
GoldMember= g.Count(c => c.MembershipType == "GoldMember"),
LifeMember= g.Count(c => c.MembershipType == "LifeMember"),
};

Resources