I have the following code:
var configItems = new List<ConfigurableItem>();
var assemblies = new List<Assembly>();
var pcbas = new List<Pcba>();
configItems.Add(new ConfigurableItem() { CiCode = "TST001", AssemblyId = "ASS001" });
configItems.Add(new ConfigurableItem() { CiCode = "TST002", AssemblyId = "ASS001" });
configItems.Add(new ConfigurableItem() { CiCode = "TST003", AssemblyId = "ASS002" });
configItems.Add(new ConfigurableItem() { CiCode = "TST004", AssemblyId = "ASS003" });
assemblies.Add(new Assembly { AssemblyId = "ASS001", PcbaId = "PCBA001"});
assemblies.Add(new Assembly { AssemblyId = "ASS002", PcbaId = "PCBA002" });
pcbas.Add(new Pcba { PcbaId = "PCBA001", Pcb = "401"});
var query = from c in configItems
join ca in (from a in assemblies join p in pcbas on a.PcbaId equals p.PcbaId into ca from x in ca.DefaultIfEmpty() select a)
on c.AssemblyId equals ca.AssemblyId into cap
from ca in cap.DefaultIfEmpty()
select new {
CiCode = c.CiCode,
AssemblyId = (ca == null ? "-" : ca.AssemblyId),
Pcb = ???
};
How can I make the LINQ query produce the following result set:
TST001 | ASS001 | PCBA001 | 401
TST002 | ASS001 | PCBA001 | 401
TST003 | ASS002 | - | -
TST004 | - | - | -
This may help
from c in configItems
join ca in (from a in assemblies join p in pcbas on a.PcbaId equals p.PcbaId into ca from x in ca.DefaultIfEmpty() select new {a,x})
on c.AssemblyId equals ca.a.AssemblyId into cap
from ca in cap.DefaultIfEmpty()
select new {
CiCode = c.CiCode,
AssemblyId = (ca == null ? "-" : ca.a.AssemblyId),
Pcb = (ca != null && ca.x != null) ?ca.x.Pcb :"-",
}
Here is working example
Related
I'm working in ASP.NET Core. I have a problem with querying rows which have same User_id and Definition_id, if there are any like that, I need ID of the row.
+----+---------+---------------+
| Id | User-id | Definition-id |
+----+---------+---------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
| 4 | 3 | 1 |
| 5 | 4 | 1 |
| 6 | 4 | 1 |
| 7 | 5 | 2 |
| 8 | 6 | 1 |
+----+---------+---------------+
I need to query table like this, to return { 5, 6 } to me, because of them having same user AND definition ids.
I've tried Groupby for both values, but I can't get the IQueryable or IGrouping to give me the id of specific row.
I'd imagine it to work like that, but it ain't.
var placementsWithDuplicates =
from p in _context.Placements
group p by new { p.User_id, p.Definition_id } into what
select new
{
Id = what.Id,
User = what.User_id,
Defi = what.Definition_id,
};
foreach (var p in placementsWithDuplicates)
{
issues.Add(new IssueModel()
{
Type = "Praxe ID[" + p.Id + "]",
Name = "User id [" + p.User + "], Definition id [" + p.Defi + "]",
Detail = "So user shouldnt have data for more definitons!"
});
};
Thanks to Satish Hirpara for best answer, it needed a little update so I post the thing that ended up working well:
var B = from p in _context.Placements
group p by new { p.User_id, p.Definition_id } into what
where what.Count() > 1
select new
{
User_id = what.Key.User_id,
Definition_id = what.Key.Definition_id
};
var placementsWithDuplicates = from A in _context.Placements
join b in B on new { A.User_id, A.Definition_id } equals new { b.User_id, b.Definition_id }
select A;
Please find below SQL query:
SELECT A.*
FROM Placements A
INNER JOIN
(SELECT User_id, Definition_id FROM Placements
GROUP BY User_Id, Definition_id
HAVING COUNT(*) > 1) B
ON A.User_id = B.User_id AND A.Defination_id =
B.Defination_id
You can create a temp table to avoid join of sub query.
If you want linq query then I tried to create it from above query, please find it below:
--- sub query
var B = from p in Placements
group p by new { p.User_id, p.Definition_id } into what
where what.count() > 1
select new
{ User_id = what.User_id,
Definition_id =what.Definition_id
};
--- join
Var result = from A in Placements
Join B ON A.User_id = B.User_id
AND A.Defination_id = B.Defination_id
Select A
Please try this one.
Try This
var placementsWithDuplicates = from p in _context.Placements.Where(m => m.User_id == m.Definition_id)
select new {
Id = p.Id,
User = p.User_id,
Defi = p.Definition_id,
};
// this is same as the top one
var placementsWithDuplicates = from p in _context.Placements where p.User_id == p.Definition_id
select new {
Id = p.Id,
User = p.User_id,
Defi = p.Definition_id,
};
foreach (var p in placementsWithDuplicates)
{
issues.Add(new IssueModel()
{
Type = "Praxe ID[" + p.Id + "]",
Name = "User id [" + p.User + "], Definition id [" + p.Defi + "]",
Detail = "So user shouldnt have data for more definitons!"
});
};
I have table Billing as below
AccoundID | Group | DateOfBill
1234 | A | 2017-07-12
1234 | B | 2017-07-16
1234 | C | 2017-07-31
1235 | A | 2017-07-31
1236 | B | 2017-07-31
As you see, AccountID 1234 have made 3 transaction on July 2017. So I need a list where the AccountID 1234 must be in Group C because that's is latest date on that transaction.
Here is my code snippet
var LatestAccount = from n in Billing
where (n.Group == "A" || n.Group == "B" || n.Group == "C")
group n by new { n.AccountID, n.Group } into g
select new {
AccountId = g.Key.AccountID,
Group = g.Key.Group ,
DateOfBill = g.Max(t => t.DateOfBill)
};
But the result is wrong. How to do in LINQ?
class Program
{
static void Main(string[] args)
{
List<Billing> Billings = new List<Billing>()
{
new Billing()
{
AccountID = 1234, DateOfBill = new DateTime(2017,07,12), Group = "A"
},
new Billing()
{
AccountID = 1234, DateOfBill = new DateTime(2017,07,16), Group = "B"
},
new Billing()
{
AccountID = 1234, DateOfBill = new DateTime(2017,07,31), Group = "C"
},
new Billing()
{
AccountID = 1235, DateOfBill = new DateTime(2017,07,31), Group = "A"
},
new Billing()
{
AccountID = 1236, DateOfBill = new DateTime(2017,07,31), Group = "B"
}
};
var LatestAccount = from n in Billings
where (n.Group == "A" || n.Group == "B" || n.Group == "C")
group n by new { n.AccountID } into g
select g.Where(d => d.DateOfBill == g.Max(m => m.DateOfBill)).Select(x => new { AccountId = g.Key.AccountID, Group = x.Group, DateOfBill = x.DateOfBill }).FirstOrDefault();
foreach (var item in LatestAccount)
{
Console.WriteLine("AccountID: " + item.AccountId + " Date of Bill: " + item.DateOfBill + " Group: "+ item.Group);
}
Console.ReadLine();
}
}
class Billing
{
public int AccountID { get; set; }
public string Group { get; set; }
public DateTime DateOfBill { get; set; }
}
Is below what you want?
If you show me the output you want, I can modify my answer.
I have a two lists rca and purchase as follow.
List<GroupDate> rca = (from sold in GetSoldOut
group sold by new { sold.CreatedDate, sold.SubCategoryID }
into g
select new GroupDate
{
Date = g.Key.CreatedDate,
SubCategoryID = g.Key.SubCategoryID,
Count = g.Count()
}).ToList();
and
List<GroupDate> purchase = (from sold in stock
group sold by new { sold.CreatedDate, sold.SubCategoryID }
into g
select new GroupDate
{
Date = g.Key.CreatedDate,
SubCategoryID = g.Key.SubCategoryID,
Count = g.Sum(a => a.Quantity)
}).ToList();
And Join this two lists as follow.
var leftOuterJoinRP = from first in replace
join last in prepaid
on new { first.Date, first.SubCategoryID } equals new { last.Date, last.SubCategoryID }
into temp
from last in temp.DefaultIfEmpty(new GroupDate { })
select new CardBalance
{
Date = first.Date,
SubCategoryID = first.SubCategoryID,
ReDemage = first.Count,
Prepaid = last.Count
};
var rightOuterJoinRP = from last in prepaid
join first in replace
on new { last.Date, last.SubCategoryID } equals new { first.Date, first.SubCategoryID }
into temp
from first in temp.DefaultIfEmpty(new GroupDate { })
select new CardBalance
{
Date = last.Date,
SubCategoryID = last.SubCategoryID,
ReDemage = first.Count,
Prepaid = last.Count
};
leftOuterJoinRP contains
Date---| Balance | OpeningStock | Prepaid | Purchase | RCA | Demage | SubCategoryId
1/1/17 | 0-------| 0----------- | 1------ | 600 -----| 2-- | 0 ---- | 84
and
rightOuterJoinRP contains
Date---| Balance | OpeningStock | Prepaid | Purchase | RCA | Demage | SubCategoryId
1/1/17 | 0-------| 0----------- | 1------ | 600-----| 2-- | 0 ---- | 84
1/2/17 | 0-------| 0----------- | 1------ | 110-----| 1-- | 0 ---- | 84
Union leftOuterJoinRP and rightOuterJoinRP as follow.
var fullOuterJoinRP = leftOuterJoinRP.Union(rightOuterJoinRP);
But it does not union. fullOuterJoinRP get all rows.
You need to use the Union method which takes an IEqualityComparer<T> parameter.
Let's say you have a TestClass
public class TestClass
{
public int TestInteger { get; set; }
public string TestString { get; set; }
}
And create two lists
List<TestClass> list1 = new List<TestClass>();
list1.Add(new TestClass() { TestInteger = 1, TestString = "t1" });
list1.Add(new TestClass() { TestInteger = 2, TestString = "t2" });
List<TestClass> list2 = new List<TestClass>();
list2.Add(new TestClass() { TestInteger = 1, TestString = "t1" });
list2.Add(new TestClass() { TestInteger = 3, TestString = "t3" });
IEnumerable<TestClass> list3 = list1.Union(list2);
Here, the Union method will return all four objects, like in your question.
The Union method needs an IEqualityComparer<TestClass> parameter to compare the objects.
public class TestClassComparer : IEqualityComparer<TestClass>
{
public bool Equals(TestClass x, TestClass y)
{
//Check whether the objects are the same object.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether the class properties are equal.
return x != null && y != null && x.TestInteger.Equals(y.TestInteger) && x.TestString.Equals(y.TestString);
}
public int GetHashCode(TestClass obj)
{
//Get hash code for the TestString field if it is not null.
int hashTestString = obj.TestString == null ? 0 : obj.TestString.GetHashCode();
//Get hash code for the TestInteger field.
int hashTestInteger = obj.TestInteger.GetHashCode();
//Calculate the hash code for the TestClass object.
return hashTestString ^ hashTestInteger;
}
}
Now, if you call
IEnumerable<TestClass> list3 = list1.Union(list2, new TestClassComparer());
The resulting list3 will have three unique objects.
I'm stuck rewriting this SQL in Lambda:
SELECT TOP 1000 COUNT(LoginDateTime)
,[LoginDateTime]
,[Culture]
FROM [LearningApp].[dbo].[UserActivities]
group by LoginDateTime, Culture
Result:
+-----+---------------------------+----------+
| | LoginDateTime | Culture |
+-----+---------------------------+----------+
| 1 | 2016-07-14 12:21:23.307 | de |
| 4 | 2016-07-13 12:21:23.307 | en |
| 2 | 2016-07-14 12:21:23.307 | en |
+-----+---------------------------+----------+
And my code:
public List<UserActivityResponseContract> GetUserActivity()
{
var userActivityResponseContracts = new List<UserActivityResponseContract>();
var userActivitiesList = _baseCommands.GetAll<UserActivity>()
.Select(x => new
{
x.LoginDateTime,
x.Culture
})
.GroupBy(x => new { x.LoginDateTime, x.Culture});
foreach (var userActivity in userActivitiesList)
{
userActivityResponseContracts.Add(new UserActivityResponseContract
{
ActivityDate = userActivity.Key.LoginDateTime.ToShortDateString(),
NumberOfTimesLoggedIn = userActivity.Count(),
Culture = userActivity.Key.Culture
});
}
return userActivityResponseContracts;
}
It doesn't seem very difficult but I am a bit stuck.
Method Syntax:
var result = _baseCommands.GetAll<UserActivity>()
.GroupBy(x => new { x.LoginDateTime, x.Culture})
.Select (x => new UserActivityResponseContract
{
ActivityDate = x.Key.LoginDateTime.ToShortDateString(),
Culture = x.Key.Culture,
NumberOfTimesLoggedIn = x.Count()
})
.Take(1000).ToList();
You can also use an overload of GroupBy that enables you to pass the select function as a second parameter
Query Syntax:
var result = (from x in _baseCommands.GetAll<UserActivity>()
group x by new { x.LoginDateTime, x.Culture} into g
select new UserActivityResponseContract
{
ActivityDate = g.Key.LoginDateTime.ToShortDateString(),
Culture = g.Key.Culture,
NumberOfTimesLoggedIn = g.Count()
}).Take(1000).ToList();
To GroupBy just the Date part of this DateTime do: x.LoginDateTime.Date
I'm trying to bind the data values to a repeater, with bank names and balance of each bank. The balance is calculated as balance = sum(debit) - sum(credit), and i'm trying to get a result like:
-------------------
bank name | amount|
------------------|
a | 1200 |
------------------|
b | 1500 |
------------------|
c | 2400 |
-------------------
for this i used the code:
protected void bank_account()
{
var balance = 0;
using (var context = new sem_dbEntities())
{
var query = (from b in context.banks
join h in context.heads on b.h_id equals h.h_id
where b.bankstatus != 3 && (h.pid == 13 || h.h_id == 9)
select new { b.acc_name, b.h_id }).Take(4);
foreach (var item in query)
{
var debit1 = (from p in context.ledgers where p.h_id == item.h_id select p.debit).Sum();
var credit1 = (from q in context.ledgers where q.h_id == item.h_id select q.credit).Sum();
balance = Convert.ToInt32( debit1 - credit1);
var query1 = (from b in context.banks
join h in context.heads on b.h_id equals h.h_id
where b.bankstatus != 3 && (h.pid == 13 || h.h_id == 9)
select new { b.acc_name, b.h_id, balance }).Take(1);
foreach (var item1 in query1)
{
Repeater1.DataSource = query1.ToList();
Repeater1.DataBind();
}
}
}
}