LINQ to SQL - CASE statement with subquery - c#

I am having trouble trying to represent the below SQL (which returns the results I want) in LINQ:
select
case r.CategoryID
when 2 then
case r.PrimaryRecord
when 1 then r.RecordID
else (select RecordID from Record where RecordGroupID = r.RecordGroupID and PrimaryRecord = 1)
end
else
r.RecordID
end
as RecordID
, r.FooID
from Record r
where
r.FooID = 3
Each row in the Record table has a unique RecordID. Multiple RecordID's could be associated with a RecordGroupID for CategoryID 2, but only one of them will have the PrimaryRecord field value of 1.
Given the below table of data, my desired output is RecordID = 1, FooID = 3, i.e. the RecordID for the given RecordGroupID that is the PrimaryRecord, but the FooID for the given row that matches my Where clause.
RecordID RecordGroupID PrimaryRecord CategoryID FooID
1 1 1 2 1
2 1 0 2 1
3 1 0 2 3
I appreciate the SQL itself probably isn't the most efficient SQL in the world but it was the best I could come up with.
If anyone could help me create the LINQ statement to represent this query that would be great.

I think you don't really need the case in the original query. Try something like:
var matchingRecords = from r in Records
where r.FooId = fooId && r.CategoryId == catId && r.RecordGroupId == groupId
join r2 in Records on r.RecordGroupId == r2.RecordGroupId && r.CategoryId == r2.CategoryId && r2.PrimaryRecord
select r2;
Edit: added CategoryId in join, assuming RecordGroupId is only unique inside a category.

Related

Simplifying LINQ query in C#

Table1
Table1ID Name Graduation Version Hobbies
1 A Degree 1 B
2 A Degree 2 C
3 A Degree 3 D
Table2
Table2ID Table1ID Name Graduation Version Address Surname Date
1 1 A Degree 1 A A 08-10-2019
2 2 A Degree 2 A A 08-10-2019
3 3 A Degree 3 A A
//I want to check if any version greater than highest version exists in Table1 .where Date column is not null in Table2
Suppose for the combination of Name and Degree , the highest version is 2 in Table2 since Date is null for Table2, I want to check if any record greater than 2 exists in Table1, if yes add it to a new List
Here is what I am doing.
List<Table2> groupByTable2 = //Operations on Table2 and get highest Version record from db
List<Table1> check = new List<Table1>();
List<Table1> check2 = await _table1.GetAll().ToListAsync();
Foreach(var a in groupByTable2)
{
List<Table1> check4 = check2.Where(x => x.Name == a.Name && x.Graduation == a.Graduation).ToList();
If(check4.Any(x=>x.Version > a.Version))
{
check.Add(check2.Where(x=>x.Table1ID == a.Table1ID).First());
}
}
Now my check contains a record where ID is 3. But is there any simpler way to achieve this in simpler way with readability and performance?
I hope I understood what you are trying to achieve. You could try the following.
var result = table2.Where(x=>x.Date!=null)
.GroupBy(x=> new {x.Name, x.Graduation})
.SelectMany(x=> x.OrderByDescending(c=>c.Version).Take(1))
.Join(table1,t2=>t2.Table1ID,t1=>t1.Table1ID,(t2,t1)=>t1)
.ToList();
result.AddRange(table1.Where(x=> result.Any(c=>c.Name.Equals(x.Name)
&& c.Graduation.Equals(x.Graduation)
&& c.Version < x.Version)));
The idea is to first use GroupBy and Join to get the List of Items with highest Version number in Table1 that has a valid date in Table2. Then, use List.AddRange to add remaining higher versions from Table1.

How to check values is existed on table using SQL Query

Table
RawID data
1 A
2 B
3 C
4 D
I have value RawID list (2,4,5). I want to know (2,4,5) is existed or not.
i have tried below
SELECT CASE WHEN EXISTS(SELECT * FROM table WHERE rawid IN (2,4,5)) THEN 1 ELSE 0 END
But 2, 4 is existed on table, it returned '1'.
But i want to get '0' because (2,4,5) all value is not existed on table.
if (1,2,3), return 1
if (2,3), return 1,
if (1,3,4) return 1
if (1,5) return 0
if (2,6) return 0
Could you give to me idea to check that all data is existed on table or not using SQL Query??
check for number no rows that matches the input. Example for rawid 2, 4, 5 there should be 3 rows
select case when (select count(*) from table where rawid in (2, 4, 5)) = 3
then 1
else 0
end
select case when (select count(*) from table where rawid in (2, 3)) = 2
then 1
else 0
end
If you want flexibility, you can do:
with vals as (
select *
from (values (2, 4, 5)) v(val)
)
select (case when count(*) = max(c.cnt) then 1 else 0 end)
from t join
vals
on t.rawid = v.val cross join
(select count(*) as cnt from vals) c;
This looks a little more complicated than other solutions, but you only have to change the values() line in the query for it to work on any number of values.
(This assumes that rowid has no duplicates.)

Linq Count and Group by

I have a SQL query that I need to turn into Linq but for the life of me I cannot seem to group the results.
This is the original SQL query:
select UserLevel, count(UserLevel) as count, StudioId
from UserProfile
where CompletedSetup = 1
and userid in (select UserId from webpages_UsersInRoles where RoleId = 4)
group by StudioId, UserLevel
order by StudioId
and what it returns is something like
UserLevel Count StudioId
1 6 1
2 2 1
3 4 1
context.UserProfile
.Where(x=>x.CompletedSetup==1 && context.webpages_UsersInRoles.Any(u=>u.UserId == x.UserId && u.RoleId == 4))
.GroupBy(x=>new {x.UserLevel, x.StudioId)
.Select(x=>new {UserLevel = x.Key.UserLevel, StudioId = x.Key.StudioId, count=x.Count()})

Recursively update values based on rows parent id SQL Server

I have the following table structure
| id | parentID | count1 |
2 -1 1
3 2 1
4 2 0
5 3 1
6 5 0
I increase count values from my source code, but i also need the increase in value to bubble up to each parent id row until the parent id is -1.
eg. If I were to increase count1 on row ID #6 by 1, row ID #5 would increase by 1, ID #3 would increase by 1, and ID #2 would increase by 1.
Rows also get deleted, and the opposite would need to happen, basically subtracting the row to be deleted' value from each parent.
Thanks in advance for your insight.
I'm using SQL Server 2008, and C# asp.net.
If you really want to just update counts, you could want to write stored procedure to do so:
create procedure usp_temp_update
(
#id int,
#value int = 1
)
as
begin
with cte as (
-- Take record
select t.id, t.parentid from temp as t where t.id = #id
union all
-- And all parents recursively
select t.id, t.parentid
from cte as c
inner join temp as t on t.id = c.parentid
)
update temp set
cnt = cnt + #value
where id in (select id from cte)
end
SQL FIDDLE EXAMPLE
So you could call it after you insert and delete rows. But if your count field are depends just on your table, I would suggest to make a triggers which will recalculate your values
You want to use a recursive CTE for this:
with cte as (
select id, id as parentid, 1 as level
from t
union all
select cte.id, t.parentid, cte.level + 1
from t join
cte
on t.id = cte.parentid
where cte.parentid <> -1
) --select parentid from cte where id = 6
update t
set count1 = count1 + 1
where id in (select parentid from cte where id = 6);
Here is the SQL Fiddle.

Linq query help

I am trying to convert this short SQL statement into linq but I am facing some difficulties, here's my latest attempt, apparently it has an error:
SQL:
select ProductID from products where
categoryID in (select categoryID from categories_sub
where categoryID='15' and category_sub_name = 'chiffon')
Linq:
'15' and 'chiffon' is replaced by parameter 'cID' and 'subCatID' here:
IQueryable<Categories_Sub > cat = (from c in db.Categories_Sub
where c.CategoryID == cID
& c.Category_Sub_ID == subCatID
select c);
var subcat = (from c in db.Products
where cat.Contains(c.ProductID)
select c);
Try
var Result = from p in products
from subc in categories_sub
where subc.categoryID=15 and
subc.category_sub_name = "chiffon" and
p.categoryID = subc.categoryID
select p.ProductID;
Minimally, your code won't compile because there is an extra space before closing generic bracket.
The first line should start with IQueryable<Categories_Sub>.
Then, there is not enough information in your question. What LINQ provider are you using? What makes you think there is an error in query?
I've reformatted the sql to talk about it in a little more depth
1 select ProductID
2 from products
3 where categoryID in
4 (select categoryID
5 from categories_sub
6 where categoryID='15' and
7 category_sub_name = 'chiffon')
Line 3 supposes you're looking for products with a specific categoryID
But your subquery starting on line 4, only returns a list of 0 or more categoryIDs that must = '15'
In which case, why not
1 select ProductID
2 from products
3 where categoryID = '15'
I know this isn't an answer but it was too big to fit inside a comment. I'll try to answer later.

Categories

Resources