This question already has answers here:
linq case statement
(6 answers)
Closed 3 years ago.
I am looking for assistance translating a SQL CASE Statement into LINQ code. Thing is, I need to implement it into code that already exists.
Basically, I need to transform memberIssues.IsClosed into the Alert Status CASE Statement below, but I've been having some difficulties.
List<IssueRowDTO> issuesList = new List<IssueRowDTO>();
if (userRoleInfo.CanViewAllIssues)
{
#region View All Issues LINQ
// If user can view all issues, then User ID check is removed.
issuesList = (from memberIssues in dbContext.MemberIssues
from issueSteps in dbContext.IssueSteps.Where(issueSteps => issueSteps.ID == memberIssues.CurrentStepID).DefaultIfEmpty()
from issueDefs in dbContext.IssueDefs.Where(issueDefs => issueDefs.ID == memberIssues.IssueDefsID).DefaultIfEmpty()
from member in dbContext.Member.Where(member => member.ID == memberIssues.MemberID).DefaultIfEmpty()
from memberTeam in dbContext.MemberTeam.Where(memberTeam => memberTeam.MemberID == memberIssues.MemberID
&& memberTeam.RoleID == issueSteps.RoleID).DefaultIfEmpty()
from userRoles in dbContext.UserRoles.Where(userRoles => userRoles.RoleID == memberTeam.RoleID
&& userRoles.UserID == memberTeam.UserID).DefaultIfEmpty()
from users in dbContext.Users.Where(users => users.ID == userRoles.UserID).DefaultIfEmpty()
from plans in dbContext.Plans.Where(plans => plans.ID == member.PlanID).DefaultIfEmpty()
where memberIssues.CreatedDate > searchFromDate
select new IssueRowDTO
{
IssueID = memberIssues.ID,
MemberID = memberIssues.MemberID,
ActionRequiredBy = users.FirstName + " " + users.LastName,
MemberName = member.FirstName + " " + member.LastName,
MLTC = plans.PlanName,
Issue = issueDefs.IssueName,
CreatedDate = memberIssues.CreatedDate,
LastUpdate = memberIssues.LastUpdate ?? memberIssues.CreatedDate,
NextDeadline = memberIssues.NextDeadline ??
memberIssues.CreatedDate,
IsClosed = memberIssues.IsClosed,
ClosedOffService = memberIssues.ClosedOffService ?? "",
SubIssueDefsID = memberIssues.SubIssueDefsID ?? 0,
CurrentStepNum = issueSteps.StepNum
})
.ToList();
SQL
CASE
WHEN CurrentStepNum > 1 THEN 'Positive'
WHEN CurrentStepNum = 1 AND memberIssues.IsClosed <> 1 THEN 'Pending'
WHEN CurrentStepNum = 1 THEN 'False Positive'
END AS 'Alert Status'
I cheated (a little). Assuming StepNum is always >= 1, you could remove the == 1 test altogether as well.
AlertStatus = (issueSteps.StepNum > 1 ? "Positive" :
issueSteps.StepNum == 1 ? (!memberIssues.IsClosed ? "Pending" : "False Positive"))
A more literal translation would be:
AlertStatus = (issueSteps.StepNum > 1 ? "Positive" :
issueSteps.StepNum == 1 && !memberIssues.IsClosed ? "Pending" :
issueSteps.StepNum == 1 ? "False Positive" : "Bad StepNum!")
Related
The fields in my Rate Table are Route, VehicleMasterId, VehicleType, Material, Client, UnitRate etc.
The priority order on which I have to fetch a single row is : VehicleNo > Route > Client > VehicleType, Material
Suppose I have 2 rows with same data except 1 has Client and Vehicle Type and the other one has VehicleNo.Then based on my priority, I should pick the rate of the row with VehicleNo.
To excute this In linq I have first picked all the rows with matching data. Here is my code.
public RateMasterDataModel GetRateMasterforCn(Consignment cn){
// I will always pass all the above fields in cn
var rateMaster = (from rate in Context.RateMaster
where rate.FromDate <= cn.Cndate
&& rate.ToDate >= cn.Cndate
&& (rate.VehicleTypeId != null ? rate.VehicleTypeId == cn.VehicleTypeId : true)
&& (rate.VehicleMasterId != null ? rate.VehicleMasterId == cn.VehicleMasterId : true)
&& (rate.ClientId != null ? rate.ClientId == cn.ClientId : true)
&& (rate.RouteId != null ? rate.RouteId == cn.RouteId : true)
&& (rate.MaterialMasterId != null ? rate.MaterialMasterId == cn.MaterialMasterId : true)
select new RateMasterDataModel
{
RateMasterId = rate.RateMasterId,
FromDate = rate.FromDate,
ToDate = rate.ToDate,
ClientId = rate.ClientId ,
VehicleMasterId = rate.VehicleMasterId,
VehicleTypeId = rate.VehicleTypeId,
MaterialMasterId = rate.MaterialMasterId,
UnitRate = rate.UnitRate,
LoadTypeId = rate.LoadTypeId,
LoadingPointId = rate.RouteId,
CalculationMasterId = rate.CalculationMasterId
}).ToList();
}
Please suggest how to filter after this.
You can use below code to get records ordered by VehicleNo > Route
.OrderBy(v=>v.VehicleNo).ThenBy(r=>r.RouteId)
Add multiple .ThenBy() clause as per your column requirement for sorting the data.
You mean to say if the row which doesn't have the vehicalno. filld-up then the row having Route must be selected.is it correct?
This question already has answers here:
How can you handle an IN sub-query with LINQ to SQL?
(9 answers)
Closed 6 years ago.
I'm completely new to LINQ, i want to rewrite some of mine SQL querys into LINQ (just to learn) and i'v already stuck at the beginning.
Here is SQL query :
declare #typMon varchar(200)
set #typMon = 'moneta'
select *
from [db1].[dbo].[Picking]
where number = 1000
and Group IN (Select grupa
from [db2].[dbo].[groups]
where typ = #typMon)
Subquery returns 3 output rows : http://i.stack.imgur.com/CDOwr.png
And here is what i'v write in LINQ
This part works ok :
var query = from x in db.grupyTowarowes
where x.typ == typMoneta
select new
{
x.grupa
};
Problem is here:
var test = from z in dbContext.PICKINGs
where z.Number == 1000
&& z.group IN output from 1st query
select new
{
z.id
};
var test = from z in dbContext.TBL_CSV_PICKINGs
join g in db.grupyTowarowes on Z.group equals g.grupa
where z.Number == 1000 &&
g.typ == typMoneta
select new { z.id };
Or in the Method syntax
dbContext.TBL_CSV_PICKINGs
.Where(z => z.Number == 1000)
.Join(db.grupyTowarowes.Where(g => g.typ == typMoneta)
z => z.group,
g => g.grupa,
(z,g) => z.id);
I have two tables employee_personals where all the personal record of the employee is stored and telephone_bills where the telephone bills paid to a particular employee is stored for each month. Now in my employeePersonalsController.php I have a function called api_show_employees() which is similar to below :
function api_show_employees() {
//$this->autoRender = false;
//Configure::write("debug",0);
$office_id = '';
$cond = '';
if(isset($_GET['office_id']) && trim($_GET['office_id']) != '') {
$office_id = $_GET['office_id'];
$cond['EmployeePersonal.office_id'] = $office_id;
}
if(isset($_GET['telephoneBillTo']) && isset($_GET['telephoneBillFrom']) ) {
if($_GET['telephoneBillTo'] != '' && $_GET['telephoneBillFrom'] != '') {
$cond['TelephoneBill.bill_from'] = $_GET['telephoneBillFrom'];
$cond['TelephoneBill.bill_to'] = $_GET['telephoneBillTo'];
}
}
$order = 'EmployeePersonal.name';
// $employee = $this->EmployeePersonal->find('all');
$employee = $this->EmployeePersonal->find('all',array('order' => $order,'conditions'=>$cond));
//return json_encode($employee);
}
This functions basically finds all the employees who paid bills in the given period. But I am getting an error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'TelephoneBill.bill_from' in 'where clause'
Models : EmployeePersonal.php:
var $hasMany = array(
'TelephoneBill' => array(
'className' => 'TelephoneBill',
)
);
TelephoneBill.php
public $name = 'TelephoneBill';
var $hasMany = array('EmployeePersonal');
NB: If I skip the bill_from and bill_to conditions, I am getting the results , with TelephoneBill array !
TLDR: use Joins instead.
Details/Notes:
1) it looks like you're using recursive. Don't do that. Use Containable instead.
2) You can't limit the parent model based on conditions against data from a contained/recursive-included table - instead, use Joins.
2b) Or, you could query from the other direction, and query your TelephoneBill with conditions, then contain the EmployeePersonal.
I am a newbie intern way over my head, I promise I have researched this thoroughly and tried many different things. The following linq query works, but I want to group rows by last and first name and then only show the rows that appear more than once. When I un-comment out the group by statement, all my aliases below become unrecognized and changing them to the actual db.table names doesn't help.
var query = from emps in db.Employees
join c in db.Cards on emps.SbiID equals c.SbiID
where c.StateID == 0 && c.CardNumberNumeric > 100000
//group emps by new {emps.Surname, emps.Name};
//orderby grp.Count() // something like 'where grp.Count > 1
select new
{
Surname = emps.Surname,
Name = emps.Name,
CorpID = emps.Identifier,
CardNum = c.CardNumber,
CostCenter = emps.EmployeeUserField.UF13,
Supervisor = (from e in db.Employees
where
e.Identifier.Equals(emps.EmployeeUserField.UF5)
select e.Surname).FirstOrDefault()
+ ", "
+ (from e in db.Employees
where e.Identifier.Equals(emps.EmployeeUserField.UF5)
select e.Name).FirstOrDefault(),
SupervisorID = emps.EmployeeUserField.UF5,
EmpCommence = emps.CommencementDateTime,
CardCommence = c.CommencementDateTime,
WorkPhone = emps.Telephone,
State = (from cf in db.ComboFields
from sp in db.StringProperties
where cf.ComboIndex.Equals(c.StateID)
&& cf.StringID.Equals(sp.StringID)
&& cf.TableName.Equals("Card")
&& cf.FieldName.Equals("StateID")
select sp.DefaultValue).FirstOrDefault()
};
this.tagsGridView.DataSource = query;
this.tagsGridView.DataBind();
I think the problem you're running into is that you're not flattening out your groups appropriately. For example:
var duplicateEmployees = db.Employees
.GroupBy(emp => emp, new EmployeeComparer())
.Where(grp => grp.Count() > 1)
.SelectMany(grp => grp.AsEnumerable());
var duplicateEmployeeInfo =
from emps in duplicateEmployees
join c in db.Cards on emps.SbiID equals c.SbiID
where c.StateID == 0 && c.CardNumberNumeric > 100000
select new
{
... what to select
};
With:
public class EmployeeComparer : IEqualityComparer<Employee>
{
public bool Equals(Employee x, Employee y)
{
return x.Surname == y.Surname && x.Name == y.Name;
}
public int GetHashCode(Employee obj)
{
unchecked { return (17 * obj.Surname.GetHashCode()) ^ (23 * obj.Name.GetHashCode()); }
}
}
This groups the employees by name, finds the groups that have a count > 1, then returns the elements of those groups. No guarantees on performance, but this should solve your issue.
I am almost done converting a MySQL app to Linq2SQL but struggling to get my head round this last SQL query
SELECT a.URL, b.URL AS DuplicateURL
FROM Pages a
INNER JOIN Pages b ON a.MetaDescription = b.MetaDescription
AND a.PageID <> b.PageID
WHERE a.DomainID = #reportid
AND b.DomainID = #reportid
AND LENGTH(TRIM(a.MetaDescription)) > 0
AND a.URL < b.URL
ORDER BY a.URL ASC
Could anymore give me some syntax help on how I would create this query in Linq2SQL?
Any help greatly appreciated
It goes like this:
var DuplicatePages =
from a in DBContext.Pages
join b in DBContext.Pages on a.MetaDescription equals b.MetaDescription
where (a.PageID <> b.PageID) && (a.DomainID == ReportID) &&
(b.DomainID == ReportID) && (a.MetaDescription.Trim().Length > 0) &&
(a.URL < b.URL)
orderby a.URL
select new { Url = a.URL, DuplicateUrl = b.URL };
That's pretty straigtforward:
var reportId = ...;
var duplicates =
from a in db.Pages
from b in db.Pages
where a.MetaDescription == b.MetaDescription
where a.PageID != b.PageID
where a.DomainID == reportId
where b.DomainID == reportId
where a.MetaDescription.Trim().Length > 0
where a.URL < b.URL
orderby a.URL
select new { Url = a.URL, DuplicateUrl = b.Url }