How to convert SQL subquery to Linq - c#

I have two tables, Employees and Transactions.
First table: dbo.Employees
Second table: dbo.Transactions
I need to convert the below query to a lambda expression (Linq):
SELECT Employees.EmployeeId, Trans.LastTrans
FROM dbo.Employees
INNER JOIN
(SELECT EmployeeId, MAX(TrasactionDate) LastTrans
FROM dbo.Transactions
GROUP BY EmployeeId) Trans ON Trans.EmployeeId = Employees.EmployeeId
I want the result employeeId and LastTrans as shown below:

See following. The query does not need two Select in linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Context db = new Context()
{
Employees = new List<Employees>() {
new Employees() { EmployeeId = 1, Name = "Hossam"},
new Employees() { EmployeeId = 2, Name = "Peter"},
new Employees() { EmployeeId = 3, Name = "George"}
},
Transactions = new List<Transactions>() {
new Transactions() { TranactionId = 1, amount = 200, TransactionDate = DateTime.Parse("2020-01-02"), EmployeeId = 1},
new Transactions() { TranactionId = 2, amount = 300, TransactionDate = DateTime.Parse("2020-02-02"), EmployeeId = 1},
new Transactions() { TranactionId = 3, amount = 1000, TransactionDate = DateTime.Parse("2020-02-25"), EmployeeId = 1},
new Transactions() { TranactionId = 4, amount = 5000, TransactionDate = DateTime.Parse("2020-04-01"), EmployeeId = 2},
new Transactions() { TranactionId = 5, amount = 7000, TransactionDate = DateTime.Parse("2020-07-16"), EmployeeId = 2},
new Transactions() { TranactionId = 6, amount = 8000, TransactionDate = DateTime.Parse("2020-08-06"), EmployeeId = 3},
new Transactions() { TranactionId = 6, amount = 600, TransactionDate = DateTime.Parse("2020-09-04"), EmployeeId = 3}
}
};
var results = (from trans in db.Transactions
join emp in db.Employees on trans.EmployeeId equals emp.EmployeeId
select new { EmployeeId = trans.EmployeeId, LastTrans = trans.TransactionDate }
).GroupBy(x => x.EmployeeId)
.Select(x => x.OrderByDescending(y => y.LastTrans))
.Select(x => x.First())
.OrderBy(x => x.EmployeeId)
.ToList();
}
}
public class Context
{
public List<Employees> Employees { get; set; }
public List<Transactions> Transactions { get; set; }
}
public class Employees
{
public int EmployeeId { get; set; }
public string Name { get; set; }
}
public class Transactions
{
public int TranactionId { get; set; }
public decimal amount { get; set; }
public DateTime TransactionDate { get; set; }
public int EmployeeId { get; set; }
}
}

This query is enough to get your result and you do not need additional join to Employees
var grouped =
from trans in db.Transactions
group trans by trans.EmployeeId into g
select new
{
EmployeeId = g.Key,
LastTrans = g.Max(x => x.TrasactionDate)
};

Related

Linq Query Join two tables getting duplicate values

using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// Customer collection
IList<Customer> CustomertList = new List<Customer>() {
new Customer() { CustomerID = 1, CustomerName = "John", OrderID = 04 } ,
new Customer() { CustomerID = 2, CustomerName = "Moin", OrderID = 07 } ,
};
// Transaction collection
IList<Transaction> TransactionList = new List<Transaction>() {
new Transaction() { TransactionID = 1, OrderID = 04, Purchased = "TV",StoreName ="Amazon"} ,
new Transaction() { TransactionID = 2, OrderID = 07, Purchased = "Laptop",StoreName ="Ebay"} ,
new Transaction() { TransactionID = 3, OrderID = 07, Purchased = "Mobile",StoreName ="Ebay"} ,
};
// LINQ Query
var result =(from Cus in CustomertList
join TRan in TransactionList on Cus.OrderID equals TRan.OrderID
select new
{
CustomerName =Cus.CustomerName,
OrderID = Cus.OrderID,
StoreName =TRan.StoreName
}).ToList();
foreach(var Cus in result){
Console.WriteLine( "Name - {0} , Order ID - {1} , StoreName - {2}",Cus.CustomerName , Cus.OrderID,Cus.StoreName);
}
}
}
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public int OrderID { get; set; }
}
public class Transaction
{
public int TransactionID { get; set; }
public int OrderID { get; set; }
public string Purchased { get; set; }
public string StoreName { get; set; }
}
Result :
Name - John, Order ID - 4, StoreName - Amazon
Name - Moin, Order ID - 7, StoreName - Ebay
Name - Moin, Order ID - 7, StoreName - Ebay
From the above code i am getting the above result,I need to show what are all order and Customer name and Store where they purchase, but i am getting duplicate values, i put the normal join query but i need below Expected result.
Expected Result :
Name - John, Order ID - 4, StoreName - Amazon
Name - Moin, Order ID - 7, StoreName - Ebay .
just try this
.....
select new
{
CustomerName = Cus.CustomerName,
OrderID = Cus.OrderID,
StoreName = TRan.StoreName
}).Distinct().ToList();
It's duplicating because your key is duplicated... If you try what Serge said it'll works fine.
// LINQ Query
var result =(from Cus in CustomertList
join TRan in TransactionList on Cus.OrderID equals TRan.OrderID
select new
{
CustomerName =Cus.CustomerName,
OrderID = Cus.OrderID,
StoreName =TRan.StoreName
}).Distinct().ToList();
OR you can group by CustomerName, OrderID and StoreName in TransactionList before your result query. Using GroupBy you won't need to use Distinct()

Datatable C# - How to get detail record from one table and its associated sub record from another table based on ID

I have a student records in datatable if I click on any single record it performs two operations.
Get Student detailed Information and it is working fine as mentioned in the image circled in green
using getJson.
I also want to get all invoices of selected student and its payments.
NOTE: Invoices can be one or more and payment also can one or more.
Issue - Circled in Red
a. I am getting No data available in table first row of datatable.
b. Only getting data from Invoice table and not getting data from payment table.
c. Not able to select record from table.
Solution / Workaround Looking for
As user select any student from list it should show all invoice and its corresponding payments then move on to next invoice and its related payments.
Example:
Student ID : 123
Invoice ID : 12345, 12347, 123479
Payments ID : 12 for invoice id 12345, 14 for 12345, 17 for 12347 and so on.
JSON CODE:
var oTable1;
oTable1 = $('#invoiceNo').dataTable();
$('#invoiceNo').on('click', 'tr', function ()
{
var stu_id = $(this).find('td').eq(0).text();
var aid = parseInt(stu_id);
//alert(aid);
$.getJSON("/Transaction/showStu_Inv_Pay",
{
id: aid
},
function (data) {
num_rows = data.length;
alert(num_rows);
var myTable = $('#inv_pay').DataTable();
myTable.clear().rows.add(myTable.data).draw();
$(data).each(function (index, item) {
$('#inv_pay tbody').append(
'<tr><td>' + this.InvoiceID +
'</td><td>' + this.InvoiceIDate +
'</td><td>' + this.Invoice_Type_Name +
'</td></tr>'
)
});
});
});
Linq Query
public IList<Transaction> GetInvByStuID()
{
try
{
DBAPPSEntities _db = new DBAPPSEntities();
this.Invoice_Type_Name = "Invoice";
IList<Transaction> List = (from q in _db.DEL_STU_INV
where q.STU_ID == this.Stu_ID
select new Transaction
{
InvoiceID = q.INVOICE_ID,
InvoiceIDate = q.Inv_Issue_Date,
InvoiceDDate = q.Inv_Due_Date,
Invoice_Month1 = q.Inv_Month_1,
Invoice_Month2 = q.Inv_Month_2,
Invoice_Month3 = q.Inv_Month_3,
Invoice_Note = q.Inv_Note,
Invoice_Adjustment = q.Adjust_Type,
Invoice_Type_Name = this.Invoice_Type_Name,
}).ToList();
return List;
}
catch
{
return null;
}
}
NOTE:- The linq query is only from invoice table and not sure how to combine with payment table and it can be altered.
Section-101
Controller - Setting Student ID
public JsonResult showStu_Inv_Pay(int id)
{
var model = new Transaction { Stu_ID = id }; // student id set to model
var data = model.GetInvByStuID();
return Json(data, JsonRequestBehavior.AllowGet);
}
Section 102
Sample Data
Section 103 - Update - 1
Section 104 - Update - 2
Try following code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication164
{
class Program
{
static void Main(string[] args)
{
DBAPPSEntities _db = new DBAPPSEntities();
_db.DEL_STU_INV = new List<DEL_STU_INV>() {
new DEL_STU_INV() { INVOICE_ID = 59456, Inv_Issue_Date = new DateTime(20,6,1), Inv_Due_Date = new DateTime(20,6,15), STU_ID = 197, STU_Name = "New_Student1", Amount = 1000},
new DEL_STU_INV() { INVOICE_ID = 59457, Inv_Issue_Date = new DateTime(20,6,1), Inv_Due_Date = new DateTime(20,6,10), STU_ID = 197, STU_Name = "New_Student2", Amount = 1000},
new DEL_STU_INV() { INVOICE_ID = 59458, Inv_Issue_Date = new DateTime(20,6,1), Inv_Due_Date = new DateTime(20,6,10), STU_ID = 103, STU_Name = "New_Student3", Amount = 1000},
new DEL_STU_INV() { INVOICE_ID = 59459, Inv_Issue_Date = new DateTime(20,6,1), Inv_Due_Date = new DateTime(20,6,10), STU_ID = 184, STU_Name = "New_Student4", Amount = 1000},
new DEL_STU_INV() { INVOICE_ID = 59460, Inv_Issue_Date = new DateTime(20,6,1), Inv_Due_Date = new DateTime(20,6,10), STU_ID = 197, STU_Name = "New_Student5", Amount = 1000}
};
_db.PAYMENT = new List<PAYMENT>() {
new PAYMENT() { PAYMENT_ID = 1, PDate = new DateTime(20,6,18), STU_ID = 197, INV_ID = 59456, Paid_Amount = 200, Balance = 800},
new PAYMENT() { PAYMENT_ID = 2, PDate = new DateTime(20,6,17), STU_ID = 934, INV_ID = 59458, Paid_Amount = 500, Balance = 500},
new PAYMENT() { PAYMENT_ID = 3, PDate = new DateTime(20,6,17), STU_ID = 197, INV_ID = 59456, Paid_Amount = 250, Balance = 550},
new PAYMENT() { PAYMENT_ID = 4, PDate = new DateTime(20,6,17), STU_ID = 197, INV_ID = 59457, Paid_Amount = 1000, Balance = 0},
new PAYMENT() { PAYMENT_ID = 5, PDate = new DateTime(20,6,17), STU_ID = 950, INV_ID = 59459, Paid_Amount = 1000, Balance = 0},
new PAYMENT() { PAYMENT_ID = 6, PDate = new DateTime(20,6,17), STU_ID = 197, INV_ID = 59456, Paid_Amount = 500, Balance = 50},
new PAYMENT() { PAYMENT_ID = 7, PDate = new DateTime(20,6,17), STU_ID = 196, INV_ID = 59458, Paid_Amount = 250, Balance = 250},
new PAYMENT() { PAYMENT_ID = 8, PDate = new DateTime(20,6,17), STU_ID = 1060, INV_ID = 59458, Paid_Amount = 250, Balance = 0}
};
int Stu_ID = 197;
var List = (from s in _db.DEL_STU_INV.Where(x => x.STU_ID == Stu_ID)
join p in _db.PAYMENT on s.INVOICE_ID equals p.INV_ID into ps
from z in ps.DefaultIfEmpty()
select new { s = s, p = (z == null)? null : z }
)
.GroupBy(x => x.s.INVOICE_ID)
.Select(x =>
new
{
invoice = new Result() { type = "Invoice", id = x.Key, date = x.First().s.Inv_Issue_Date, amount = x.First().s.Amount },
payments = x.Select(y => (y.p == null)? null : new Result() { type = "Payment", id = y.p.PAYMENT_ID, date = y.p.PDate, amount = y.p.Paid_Amount })
}).Select(y => (y.payments.Count() == 1) ? new List<Result>() { y.invoice } : (new List<Result>() { y.invoice }).Concat(y.payments).ToList())
.ToList();
}
}
public class DBAPPSEntities
{
public List<DEL_STU_INV> DEL_STU_INV { get;set;}
public List<PAYMENT> PAYMENT { get; set; }
}
public class DEL_STU_INV
{
public int STU_ID { get; set; }
public string STU_Name{ get;set;}
public int INVOICE_ID { get; set; }
public int Amount { get; set;}
public DateTime Inv_Issue_Date { get; set; }
public DateTime Inv_Due_Date { get; set; }
public string Inv_Month_1 { get; set; }
public string Inv_Month_2 {get; set; }
public string Inv_Month_3 { get; set; }
public string Inv_Note { get; set; }
public string Adjust_Type { get; set; }
}
public class PAYMENT
{
public int PAYMENT_ID { get; set; }
public DateTime PDate { get; set; }
public int STU_ID { get; set; }
public int INV_ID { get; set; }
public int Paid_Amount { get; set; }
public int Balance { get; set; }
}
public class Transaction
{
public int InvoiceID { get;set;}
public DateTime InvoiceIDate { get;set;}
public DateTime InvoiceDDate { get;set;}
public string Invoice_Month1 { get;set;}
public string Invoice_Month2 { get;set;}
public string Invoice_Month3 { get;set;}
public string Invoice_Note { get;set;}
public string Invoice_Adjustment { get; set; }
public string Invoice_Type_Name { get; set; }
}
public class Result
{
public string type { get; set; }
public int id { get; set; }
public DateTime date { get; set; }
public int amount { get; set; }
}
}

Convert flat db row data to nested typed objects linq

I'm getting the results of a sql outer join as flat results in an IEnumerable, and would like to convert them to nested typed objects in linq. From something like this:
[{id: 1, industryId: 1}, {id:1, industryId: 2}, {id:2, industryId: 1} etc..]
to something like this:
list of Company [{id: 1, list of Industry{industryId: 1, 2}, {id: 2, list of Industry{industryId: 1}}]
I'm currently trying a solution with GroupBy:
Companies = flatDbRows
.GroupBy(
row => row.CompanyId,
(key, value) => new CompanyModel
{
CompanyId = value.First().CompanyId,
CompanyName = value.First().CompanyName,
Industries = value
.GroupBy(
row => new { row.IndustryId, row.Industry },
(k, v) => new IndustryModel() { IndustryId = k.IndustryId, Name = k.Industry }
)
.Where(x => x.IndustryId != 0)
.ToList(),
}).ToList();
}
but it doesn't feel great, especially with all the value.First() I'm using to get the values that only belong to each grouped company. Is there something more appropriate? Group join sounded more like what I wanted, but I'm having trouble understanding how to apply it to a single list. I'm open to using query syntax instead of the lambdas if that's easier.
I'm trying to go from this model (where company-related info will be duplicated for each outer joined industry result):
public class CompanyFlatDbRowsModel
{
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public int IndustryId{ get; set; }
public string Industry { get; set; }
}
to this:
public class CompanyModel
{
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public IEnumerable<IndustryModel> Industries { get; set; }
}
// FULL edit after providing your models
public class TestClass
{
public class CompanyModel
{
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public List<IndustryModel> Industires { get; set; }
}
public class IndustryModel
{
public int IndustryId { get; set; }
public string IndustryName { get; set; }
}
public class CompanyFlatDbRowsModel
{
public CompanyFlatDbRowsModel()
{
}
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public int IndustryId { get; set; }
public string Industry { get; set; }
}
[Fact]
public void Test()
{
var data = new List<CompanyFlatDbRowsModel>
{
new CompanyFlatDbRowsModel
{
CompanyId = 1,
CompanyName = "Company 1",
IndustryId = 1,
Industry = "Industry 1"
},
new CompanyFlatDbRowsModel
{
CompanyId = 1,
CompanyName = "Company 1",
IndustryId = 2,
Industry = "Industry 2"
},
new CompanyFlatDbRowsModel
{
CompanyId = 2,
CompanyName = "Company 2",
IndustryId = 3,
Industry = "Industry 3"
},
new CompanyFlatDbRowsModel
{
CompanyId = 2,
CompanyName = "Company 2",
IndustryId = 4,
Industry = "Industry 4"
},
};
var result = data.GroupBy(x => x.CompanyId)
.Select(x => new CompanyModel()
{
CompanyId = x.Key,
CompanyName = x.First().CompanyName,
Industires = x.Select(y=> new IndustryModel
{
IndustryName = y.Industry,
IndustryId = y.IndustryId
}).ToList()
}).ToList();
foreach (var item in result)
{
var text = $"Company id : {item.CompanyId}, industries : {string.Join(',',item.Industires.Select(x=>$"(name: {x.IndustryName}, id: {x.IndustryId})"))}";
Debug.WriteLine(text);
}
}
}
output:
Company id : 1, industries : (name: Industry 1, id: 1),(name: Industry 2, id: 2)
Company id : 2, industries : (name: Industry 3, id: 3),(name: Industry 4, id: 4)
edit:
alternatively you can do as below, however the "first" thing still occurs somewhere, I have tried also the GroupJoin but it doesn't really help in that case.
var otherResult = data.Select(x =>
new CompanyModel
{
CompanyId = x.CompanyId,
CompanyName = x.CompanyName,
Industires = data
.Where(y => y.CompanyId == x.CompanyId)
.Select(y => new IndustryModel
{
IndustryId = y.IndustryId,
IndustryName = y.Industry
}).ToList()
})
.GroupBy(y => y.CompanyId)
.Select(x => x.First())
.ToList();
edit:
one more approach without using "first"
var anotherResult = data.GroupBy(x => x.CompanyId)
.Select(x =>
{
var companyModel = new CompanyModel()
{
CompanyId = x.Key
};
companyModel.Industires = x.Select(y =>
{
companyModel.CompanyName = y.CompanyName; // assignign here occurs multiple times however with the same value
return new IndustryModel
{
IndustryId = y.IndustryId,
IndustryName = y.Industry
};
}).ToList();
return companyModel;
}).ToList();

RavenDB - Indexing and querying complex hierarhical data (nested properties)

I have a docuemnt like this:
public class Order
{
public string ClientName { get; set; }
public List<OrderItem> Items { get; set; }
}
public class OrderItem
{
public string ProductCode { get; set; }
public int Quantity { get; set; }
}
And I need to query collection of theese documents like this:
var q = session.Query<Order_Index.Result, Order_Index>()
.Where(o => o.ClientName.StartsWith("Jho") &&
o.Items.Any(i => i.ProductCode == "Book" && i.Quantity >= 10))
.OfType<Order>();
Every example of indexing and querying hierarhical data, that I found, shows only case, when only one property of complex nested object is used in separate query expression. e.g.:
var q = session.Query<Order_Index.Result, Order_Index>()
.Where(o => o.ClientName.StartsWith("Jho") &&
o.ItemProductCodes.Any(c => c == "Book") &&
o.ItemQuantities.Any(qty => qty >= 10))
but none of them consider my situation.
I tried to index ProductCode and Quantity as separate collections and then join them by collection index while querying, but this throws some kind of Linq translation exception. I wonder, is there any opportunity to do this kind of querying in RavenDB?
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<Order> session = new List<Order>() {
new Order() { ClientName = "Jho", Items = new List<OrderItem>() {
new OrderItem() { ProductCode = "abc", Quantity = 1},
new OrderItem() { ProductCode = "def", Quantity = 4},
new OrderItem() { ProductCode = "Book", Quantity = 5},
new OrderItem() { ProductCode = "jkl", Quantity = 10}
}
},
new Order() { ClientName = "Mary", Items = new List<OrderItem>() {
new OrderItem() { ProductCode = "mno", Quantity = 2},
new OrderItem() { ProductCode = "pqr", Quantity = 3},
new OrderItem() { ProductCode = "stu", Quantity = 4},
new OrderItem() { ProductCode = "vwx", Quantity = 5}
}
},
new Order() { ClientName = "Jho", Items = new List<OrderItem>() {
new OrderItem() { ProductCode = "abc", Quantity = 28},
new OrderItem() { ProductCode = "cdf", Quantity = 7},
new OrderItem() { ProductCode = "Book", Quantity = 26},
new OrderItem() { ProductCode = "jkl", Quantity = 5}
}
}
};
var q = session.Where(o => o.ClientName.StartsWith("Jho") && o.Items.Where(i => i.ProductCode == "Book" && i.Quantity >= 10).Any()).ToList();
}
}
public class Order
{
public string ClientName { get; set; }
public List<OrderItem> Items { get; set; }
}
public class OrderItem
{
public string ProductCode { get; set; }
public int Quantity { get; set; }
}
}

How to translate t-sql sum() to linq sum()

I have something like this:
And I need to re-write this query into LINQ.
I tried:
var EachProduct = (from b in _context.ReleasePlans
join a in _context.Products
on b.ProductProductId equals a.ProductId
where b.DepartmentDepartmentId == departmentId
select new { ProductId = b, ProductName = a });
But how can I do SUM() and DATEPART() function in Linq?
UPD: Query using lambda expression. But the question remains the same
var EachProduct = _context.ReleasePlans
.Where(b => b.DepartmentDepartmentId == departmentId)
.Join(_context.Products, a => a.ProductProductId, b => b.ProductId,
(b, a) => new {ProductId = b, ProductName = a});
class Program
{
public class ReleasePlan
{
public int ProductProductId { get; set; }
public int Amount { get; set; }
public DateTime DateTime { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int DepartmentDepartmentId { get; set; }
}
static void Main()
{
var products = new List<Product>
{
new Product {ProductId = 1, ProductName = "1", DepartmentDepartmentId = 1},
new Product {ProductId = 2, ProductName = "2", DepartmentDepartmentId = 1},
new Product {ProductId = 3, ProductName = "3", DepartmentDepartmentId = 1},
};
var releasePlans = new List<ReleasePlan>
{
new ReleasePlan {ProductProductId = 1, Amount = 1, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 1, Amount = 1, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 1, Amount = 1, DateTime = DateTime.Now.AddMonths(-5)},
new ReleasePlan {ProductProductId = 2, Amount = 2, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 2, Amount = 2, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 2, Amount = 2, DateTime = DateTime.Now.AddMonths(-5)},
new ReleasePlan {ProductProductId = 3, Amount = 3, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 3, Amount = 3, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 3, Amount = 3, DateTime = DateTime.Now.AddMonths(-5)},
};
var amountByProducts = from rp in releasePlans
join p in products
on rp.ProductProductId equals p.ProductId
where p.DepartmentDepartmentId == 1 && (rp.DateTime.AddDays(2).Month/3) == 1
group new {rp, p} by new {rp.ProductProductId, p.ProductId, p.ProductName}
into grp
select new
{
grp.Key.ProductId,
grp.Key.ProductName,
PlannedAmount = grp.Sum(g => g.rp.Amount)
};
Console.WriteLine("ProductId ProductName PlannedAmount");
foreach (var producAmount in amountByProducts)
{
Console.WriteLine("{0} \t\t{1} \t\t{2}", producAmount.ProductId, producAmount.ProductName,
producAmount.PlannedAmount);
}
}
}

Categories

Resources