I have this code, where I'm union data from 2 tables
var test =
(from table1 in db.Products
select new UnionTable()
{
ProductNumber = table1.ProductNumber,
OrderNumber = 0,
Cost = table1.Cost,
Price = table1.Price,
Name = table1.Name,
Amount = 0,
Inventory = table1.Inventory
}).Union
(from table2 in db.OrderItems
select new UnionTable()
{
ProductNumber = table2.ProductNumber,
OrderNumber = table2.OrderNumber,
Cost = 0,
Price = 0,
Name = string.Empty,
Amount = table2.Amount,
Inventory = 0
});
the output is
what I'm trying to do, is to fill the missing places with data. for example in name, I want all places where Product Number is 1, to be almond.
in price where Product Number is 1, all columns to be 10
How can I fix this?
You could always try something like this:
var test =
(from table1 in db.Products
select new UnionTable()
{
ProductNumber = table1.ProductNumber,
OrderNumber = 0,
Cost = table1.Cost,
Price = table1.Price,
Name = table1.Name,
Amount = 0,
Inventory = table1.Inventory
}).Union
(from table2 in db.OrderItems
select new UnionTable()
{
ProductNumber = table2.ProductNumber,
OrderNumber = table2.OrderNumber,
Cost = 0,
Price = table1.Price == 0 && table1.ProductNumber == 1 ? 10 : table1.Price,
Name = table1.Name == string.Empty && table1.ProductNumber == 1 ? "Almond" : table1.Name,
Amount = table2.Amount,
Inventory = 0
});
Not the most clean solution but it should do the job
Related
i have 2 table ,
produk table
id produk batch qty
1 AAA ADADAD 2
2 BBB ADADAD 2
3 BBB AAAAAA 2
...............
and move table,
id produk batch qty
1 BBB ADADAD 1
and i want showing table after qty from stok table minus qty from move table, what i want table
PRODUK BATCH QTY
AAA ADADAD 2
BBB ADADAD 1
BBB AAAAAA 2
and this my query
var obj = _db.produk
.Groupby(a=> new {a.code,a.batch})
.Select(a=> new {
produk = a.key.code,
batch = a.Key.batch,
qty = _db.move.Where(c => a.Any(p => p.code == a.code && p.batch == a.batch)).Sum(a=>a.qty)
}).tolist();
but not working
You have to do LEFT JOIN to grouped move table.
var moves =
from m in _db.move
group m by { m.code, m.batch } into g
select
{
g.Key.code,
g.Key.batch,
qty = g.Sum(x => x.qty)
};
var query =
from p in _db.produk
join m in moves on new { p.code, p.batch } equals { m.code, m.batch } into j
from m in j.DefaultIfEmpty()
select new
{
produk = p.code,
batch = p.batch.
qty = p.qty - (int?)m.qty ?? 0
};
If you prefer method syntax over query syntax then you can write your query as this:
var availableItems = repository
.GroupJoin(purchases,
stock => new { stock.Product, stock.Batch },
move => new { move.Product, move.Batch },
(stock, moves) => new { Stock = stock, Moves = moves })
.SelectMany(
stockAndRelatedMoves => stockAndRelatedMoves.Moves.DefaultIfEmpty(),
(stockAndRelatedMoves, relatedMove) => new
{
stockAndRelatedMoves.Stock.Product,
stockAndRelatedMoves.Stock.Batch,
Quantity = stockAndRelatedMoves.Stock.Quantity - (relatedMove?.Quantity ?? 0)
})
.ToList();
As you can see instead of GroupBy you need to use GroupJoin and instead of simple Select you need SelectMany to retrieve items from the joined records.
Some explanation:
stock => new { stock.Product, stock.Batch }: Anonymous type is used here because multiple fields are used in the join
stockAndRelatedMoves => stockAndRelatedMoves.Moves.DefaultIfEmpty(): it is needed because of left outer join
(relatedMove?.Quantity ?? 0): relatedMove can be null that's why we substitute it with 0
In the above code I've used the following collections:
var repository = new List<Stock>
{
new Stock { Id = 1, Product = "AAA", Batch = "ADADAD", Quantity = 2 },
new Stock { Id = 2, Product = "BBB", Batch = "ADADAD", Quantity = 2 },
new Stock { Id = 3, Product = "BBB", Batch = "AAAAAA", Quantity = 2 },
};
var purchases = new List<Move>
{
new Move { Id = 1, Product = "BBB", Batch = "ADADAD", Quantity = 1 }
};
You could also query the produck table, then, in the Select statement, filter the move table based on the produck's batch and produck properties, then calculate the qty.
Code as below:
List<Produk> produks = new List<Produk>()
{
new Produk(){ id = 1, produk= "AAA", batch="ADADAD", qty = 2},
new Produk(){ id = 2, produk= "BBB", batch="ADADAD", qty = 2},
new Produk(){ id = 3, produk= "BBB", batch="AAAAAA", qty = 2},
};
List<Remove> removes = new List<Remove>()
{
new Remove(){ id=1, produk="BBB", batch="ADADAD", qty=1}
};
var result = (from p in produks
select new Produk
{
id = p.id,
produk = p.produk,
batch = p.batch,
qty = p.qty - removes.Where(c => c.produk == p.produk && c.batch == p.batch).Sum(c => c.qty)
}).ToList();
The result like this:
I have two model classes of which I have provided the sql table structure
CREATE TABLE [DBO].[TBL_PRODUCTION] ( -- class ProductionModel
PRODUCTION_ID INT IDENTITY(1, 1) NOT NULL
,PRODUCTION_NAME NVARCHAR(200) NOT NULL
,PRODUCTION_TYPE INT NOT NULL
,PRODUCTION_QUANTITY INT
,CONSTRAINT PK_PRODUCTION PRIMARY KEY (PRODUCTION_ID)
)
INSERT INTO [DBO].[TBL_PRODUCTION] VALUES ('SGU',1, 100)
INSERT INTO [DBO].[TBL_PRODUCTION] VALUES ('BGU',1, 100)
INSERT INTO [DBO].[TBL_PRODUCTION] VALUES ('CCGU',2, 150)
CREATE TABLE [DBO].[TBL_DISTRIBUTOR] ( class DistributorModel
DISTRIBUTOR_ID INT IDENTITY(1, 1) NOT NULL
,PRODUCTION_ID INT NOT NULL
,QUARTER_TYPE INT NOT NULL
,DEMAND_QUANTITY INT
,CONSTRAINT PK_DISTRIBUTOR PRIMARY KEY (DISTRIBUTOR_ID)
)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (1,555,1,25)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (1,555,2,25)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (1,655,3,25)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (2,555,1,25)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (2,745,2,25)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (3,745,3,25)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (1,745,3,10)
INSERT INTO [DBO].[TBL_DISTRIBUTOR] VALUES (2,745,3,50)
I need to show data about total distribution on quarterly basis. I mean how many total productions are distributed in each quarter and the remaining production quantity. I have made the sql query but how to design LINQ query for the same. I have excluded the remaining quantity in SQL Query but need to show in LINQ Query.
SQL Query
SELECT
A.PRODUCTION_ID
,B.PRODUCTION_NAME
,A.QUARTER_TYPE
,B.PRODUCTION_QUANTITY
,SUM(A.DEMAND_QUANTITY) [TOTAL DISTRIBUTED]
FROM [DBO].[TBL_DISTRIBUTOR] A
INNER JOIN [DBO].[TBL_PRODUCTION] B ON A.PRODUCTION_ID = B.PRODUCTION_ID
GROUP BY
A.PRODUCTION_ID
,B.PRODUCTION_NAME
,B.PRODUCTION_QUANTITY
,A.QUARTER_TYPE
ORDER BY A.PRODUCTION_ID
I am just learning LINQ query so do not have idea how to express this in sql query in LINQ. I have the POCO Class too, now how to proceed further.
public class DistributorViewModels
{
public int PRODUCTION_ID { get; set; }
public string PRODUCTION_NAME { get; set; }
public int QUARTER_TYPE { get; set; }
public int PRODUCTION_QUANTITY { get; set; }
public int TOTAL_DISTRIBUTED { get; set; }
public int REMAINING_QUANTITY { get; set; }
}
Please see the attached image for what is my desired output.
Hoping for positive response. Thank You to all!!!
firstly some thoughts:
Does it make sense to group by production quanitity?
Also does it make sense to group by production name if you have already grouped by production id?
Based on those thoughts I would created following linq statements (the beginning is only data from your desired output):
List<DISTRIBUTOR> tbl_distribution = new List<DISTRIBUTOR>(){
new DISTRIBUTOR{PRODUCTION_ID = 1, QUARTER_TYPE = 1, DEMAND_QUANTITY = 15},
new DISTRIBUTOR{PRODUCTION_ID = 1, QUARTER_TYPE = 1, DEMAND_QUANTITY = 10},
new DISTRIBUTOR{PRODUCTION_ID = 1, QUARTER_TYPE = 2, DEMAND_QUANTITY = 25},
new DISTRIBUTOR{PRODUCTION_ID = 1, QUARTER_TYPE = 3, DEMAND_QUANTITY = 35},
new DISTRIBUTOR{PRODUCTION_ID = 2, QUARTER_TYPE = 1, DEMAND_QUANTITY = 25},
new DISTRIBUTOR{PRODUCTION_ID = 2, QUARTER_TYPE = 2, DEMAND_QUANTITY = 25},
new DISTRIBUTOR{PRODUCTION_ID = 2, QUARTER_TYPE = 3, DEMAND_QUANTITY = 50},
new DISTRIBUTOR{PRODUCTION_ID = 3, QUARTER_TYPE = 3, DEMAND_QUANTITY = 25},
};
List<PRODUCTION> tbl_production = new List<PRODUCTION>{
new PRODUCTION{ PRODUCTION_ID = 1, PRODUCTION_NAME = "SGU", PRODUCTION_QUANTITY = 100},
new PRODUCTION{ PRODUCTION_ID = 2, PRODUCTION_NAME = "BGU", PRODUCTION_QUANTITY = 100},
new PRODUCTION{ PRODUCTION_ID = 3, PRODUCTION_NAME = "CCGU", PRODUCTION_QUANTITY = 150},
};
var temp = from a in tbl_distribution
join b in tbl_production on a.PRODUCTION_ID equals b.PRODUCTION_ID
let totalProductDistributed = tbl_distribution.Where(t => t.PRODUCTION_ID == a.PRODUCTION_ID ).Sum(t => t.DEMAND_QUANTITY)
select new {
PRODUCTION_ID = a.PRODUCTION_ID,
PRODUCTION_NAME = b.PRODUCTION_NAME,
QUARTER_TYPE = a.QUARTER_TYPE,
PRODUCTION_QUANTITY = b.PRODUCTION_QUANTITY,
TOTAL_DISTRIBUTED = totalProductDistributed,
REMAINING_QUANTITY = b.PRODUCTION_QUANTITY - totalProductDistributed
};
var ViewModel = from s in temp group s by new{s.PRODUCTION_ID, s.QUARTER_TYPE} into g
select g.FirstOrDefault();
But you can also group by production id and have a table of quarterly infos. That would be just a single linq statement and you can achive your "merged" rows in one column:
var ViewModel2 = from a in tbl_distribution group a by a.PRODUCTION_ID into g
join b in tbl_production on g.FirstOrDefault().PRODUCTION_ID equals b.PRODUCTION_ID
let quarterInfos = from c in g
group c by c.QUARTER_TYPE into d
select new
{
Quarter = d.FirstOrDefault().QUARTER_TYPE,
DemandQuantity = d.Sum(t => t.DEMAND_QUANTITY),
}
select new{
g.Key,
b.PRODUCTION_NAME,
b.PRODUCTION_QUANTITY,
QuarterInfos = quarterInfos,
RemainingQuantity = b.PRODUCTION_QUANTITY - quarterInfos.Sum(i => i.DemandQuantity)
};
Scenario is,
im using EntityFrame Work 6. I have a DB have table having structure below.
cat_id geo_id parent_id geo_name
Root 1 NULL Pakistan
Province 2 1 Punjab
District 3 2 Attock
City 4 3 Attock
City 5 3 Fateh Jang
City 6 3 Hasan Abdal
Table have hierarchical data in relational form,as you can see.
I want to traverse this hierarchy, want to specific parent level, If im at geo_id 6 then I want to go parent_id 3 and get value Attock or want to go to parent_id 2 and want to get value Punjab.
Moral of the story is,standing at any child,want traverse till specified parent or grand parent,not entire hierarchy. Below is code I have tried but it gives me only its immediate parent.
More Shortly, Want a LINQ query,which will return name of specified parent or grand parent,For Example. I can ask my query, "hey! im Hasan Abdal(City),tell me my Province"
Province = (from cp in db.geo_hierarchy
join mp in db.geo_hierarchy on cp.parent_id equals mp.geo_id
where cp.geo_name == risk.geo_hierarchy.geo_name
select mp.geo_name).FirstOrDefault()
see full code below,it used in inside LINQ query's select clause
Risklists = (from risk in db.risk_cat_detail
where risk.occurance_date.Value.Year==2014 && risk.occurance_date.Value.Month>=6 && risk.occurance_date.Value.Month<=9
select new risk_cat_detail_contract()
{
cat_id = risk.cat_id,
catdesc = risk.category_main.cat_name,
risk_cat_detail_id = risk.risk_cat_detail_id,
trans_date = risk.trans_date.Value,
occurance_date = risk.occurance_date.Value,
occurance_time = risk.occurance_time,
geo_id = risk.geo_id,
geo_desc = risk.geo_hierarchy.geo_name,
Province = (from cp in db.geo_hierarchy
join mp in db.geo_hierarchy on cp.parent_id equals mp.geo_id
where cp.geo_name == risk.geo_hierarchy.geo_name
select mp.geo_name).FirstOrDefault()
}).ToList<risk_cat_detail_contract>();
Help me out,Thanks in Advance
Try this:
var geo_hierarchy = new []
{
new { cat_id = "Root", geo_id = 1, parent_id = (int?)null, geo_name = "Pakistan", },
new { cat_id = "Province", geo_id = 2, parent_id = (int?)1, geo_name = "Punjab", },
new { cat_id = "District", geo_id = 3, parent_id = (int?)2, geo_name = "Attock", },
new { cat_id = "City", geo_id = 4, parent_id = (int?)3, geo_name = "Attock", },
new { cat_id = "City", geo_id = 5, parent_id = (int?)3, geo_name = "Fateh Jang", },
new { cat_id = "City", geo_id = 6, parent_id = (int?)3, geo_name = "Hasan Abdal", },
};
var map = geo_hierarchy.ToDictionary(x => x.geo_id);
Func<int, string, string> up = null;
up = (geo_id, cat_id) =>
{
var record = map[geo_id];
return
record.cat_id == cat_id
? record.geo_name
: (record.parent_id.HasValue
? up(record.parent_id.Value, cat_id)
: null);
};
var result = up(5, "Province"); // -> "Punjab"
I have there tables as you can see :
line:
id Linename
1 line1
2 line2
3 line3
joint:
id lineId jointname
1 1 joint1
2 2 joint2
3 1 joint3
fitup:
id jointid fitupdate state
1 1 2012/12/12 acc
2 1 2013/12/12 rej
3 2 2015/12/12 acc
4 2 2016/12/12 rej
Result i need:
id Linename jointname fitupdate state
1 line1 joint1 2013/12/12 rej
2 line2 joint2 2016/12/12 rej
The fitup table has a state I need the final state based on max id.
In the fitup table i have multi rows for each joint but i need the date(string) of max id in the result query .
Here is my query:
var q = from j in _ctx.Joints
join l in _ctx.Lines on j.LineId equals l.Id
join spo in _ctx.Spools on j.SpoolId equals spo.Id
join sup in _ctx.Supports on j.SupportId equals sup.Id
join shee in _ctx.Sheets on j.SheetId equals shee.Id
join Fit in _ctx.FitUpDetails on j.Id equals Fit.JointId into g2
from y2 in g2.DefaultIfEmpty()
join weld in _ctx.WeldDetails on j.Id equals weld.JointId into g
from y1 in g.DefaultIfEmpty()
join end in _ctx.Ends on j.EndId equals end.Id
join basemat in _ctx.BaseMaterials on j.BaseMaterialId equals basemat.Id
join TestPack in _ctx.TestPackages on j.TestPackageId equals TestPack.Id
group new { j, l,y2,y1} by new { shee, j, l, spo, sup, y2, y1, end, basemat, TestPack } into grouping
let maxFitById = grouping.Select(item => item.y2)
.Where(item => item != null)
.OrderByDescending(item => item.Id)
let maxweldById = grouping.Select(item => item.y1)
.Where(item => item != null)
.OrderByDescending(item => item.Id)
select new ViewFront()
{
Id = grouping.Key.j.Id,
LineId = grouping.Key.l.LineNumber,
SubmitDateTime = grouping.Key.j.SubmitDateTime,
JointNumber = grouping.Key.j.JointNumber,
BaseMaterialId = grouping.Key.basemat.Name,
FitUpAccept = maxFitById.FirstOrDefault().StateStep1,
FitUpAcceptMain = maxFitById.FirstOrDefault().StateStep2,
JointClass = grouping.Key.j.JointClass,
End = grouping.Key.end.Name,
JointSize = grouping.Key.j.JointSize,
LeftMaterialItemCode = grouping.Key.j.LeftMaterialItemCode,
LeftMaterialLength = grouping.Key.j.LeftMaterialLength.ToString(),
MagneticTest = grouping.Key.j.MagneticTest,
PenetrationTest = grouping.Key.j.PenetrationTest,
PostWeldHeatTreatment = grouping.Key.j.PostWeldHeatTreatment,
RemarkState = grouping.Key.j.RemarkState,
RightMaterialItemCode = grouping.Key.j.RightMaterialItemCode,
RightMaterialLength = grouping.Key.j.RightMaterialLength.ToString(),
RadiographyTest = grouping.Key.j.RadiographyTest,
SheetId = grouping.Key.shee.SheetNumber,
ShopField = grouping.Key.j.ShopField,
SpoolId = grouping.Key.spo.SpoolNumber,
SupportId = grouping.Key.sup.SupportNumber,
TestPackageId = grouping.Key.TestPack.PackageNumber,
THK = grouping.Key.j.THK,
UltrasonicTest = grouping.Key.j.UltrasonicTest,
WeldAccept = maxweldById.FirstOrDefault().StateStep1,
WeldAcceptMain = maxweldById.FirstOrDefault().StateStep2
};
In this query FitUpAccept is the state .
Joint table data
weld :
fitup:
result:
The following code does what you need. Now some explanations:
I kept only the tables relevant for the described output data just to keep it simpler.
When grouping by - If you select the entire objects as you did then you will always get "groups" of a single record - I group the wanted data just by the key - In this case the non aggregated fields. Make sure that you are not grouping by the same fields that you want to actually do aggregation operations by them ( like y2 )
Because it is a left join to the FitUpDetails I must make sure that I remove all the null records and whenever I access a property of that object to make sure it is not null - c# 6.0 syntax of ?..
Now for the By max id part - if I put it into words: "Grouping the data by X, and then for each group ordering it by Y, take first record -> its properties"
So to the code:
var result = (from j in Joints
join l in Lines on j.LineId equals l.Id
join f in FitUpDetails on j.Id equals f.JointId into g2
from y2 in g2.DefaultIfEmpty()
group new { j, l, y2 } by new { j.Id, l.LineName, j.JointName } into grouping
let maxFitById = grouping.Select(item => item.y2)
.Where(item => item != null)
.OrderByDescending(item => item.Id)
.FirstOrDefault()
select new
{
Id = grouping.Key.Id,
LineName = grouping.Key.LineName,
JointName = grouping.Key.JointName,
FitUpdate = maxFitById?.FitUpdate,
State = maxFitById?.State
}).ToList();
Used this for testing it:
List<dynamic> Joints = new List<dynamic>
{
new { Id = 1, LineId = 1, JointName = "joint1" },
new { Id = 2, LineId = 2, JointName = "joint2" },
new { Id = 3, LineId = 1, JointName = "joint3" },
};
List<dynamic> Lines = new List<dynamic>
{
new { Id = 1, LineName = "line1" },
new { Id = 2, LineName = "line2" },
new { Id = 3, LineName = "line3" },
};
List<dynamic> FitUpDetails = new List<dynamic>
{
new { Id = 1, JointId = 1, FitUpdate = new DateTime(2012,12,12), State = "acc" },
new { Id = 2, JointId = 1, FitUpdate = new DateTime(2013,12,12), State = "rej" },
new { Id = 1, JointId = 2, FitUpdate = new DateTime(2015,12,12), State = "acc" },
new { Id = 4, JointId = 2, FitUpdate = new DateTime(2016,12,12), State = "rej" },
};
Hi I am running one Linq query to join three tables. below is the query...
answerText = ds.Tables[0];
questionAvg = ds.Tables[1];
interviews = ds.Tables[2];
var data = from at in answerText.AsEnumerable()
join qa in questionAvg.AsEnumerable() on at.Field<int>("ID") equals qa.Field<int>("DealerID")
join inter in interviews.AsEnumerable() on at.Field<int>("ID") equals inter.Field<int>("DealerID")
select new
{
DealerID = at.Field<int>("ID"),
DealerName = at.Field<string>("Name"),
AnswerText1 = at.Field<int?>("12"),
AnswerText2 = at.Field<int?>("8"),
AnswerText3 = at.Field<int?>("4"),
AnswerText4 = at.Field<int?>("0"),
AnswerText5 = at.Field<int?>("-4"),
Rank = qa.Field<Int64?>("Rank"),
Average = qa.Field<decimal?>("Average"),
N = inter.Field<int?>("N")
};
now sometimes answerText datatable will only have column 12 and 8.., so it is missing columns 4 0 -4. how should i avoid that column check in above query and just provide 0 there.
I'm not 100% sure what you're asking about, but I assumed you need AnswerText properties to be int not int?. And they should be set to 0 when item is not present. You can use ?? operator:
var data = from at in answerText.AsEnumerable()
join qa in questionAvg.AsEnumerable() on at.Field<int>("ID") equals qa.Field<int>("DealerID")
join inter in interviews.AsEnumerable() on at.Field<int>("ID") equals inter.Field<int>("DealerID")
select new
{
DealerID = at.Field<int>("ID"),
DealerName = at.Field<string>("Name"),
AnswerText1 = at.Field<int?>("12") ?? 0,
AnswerText2 = at.Field<int?>("8") ?? 0,
AnswerText3 = at.Field<int?>("4") ?? 0,
AnswerText4 = at.Field<int?>("0") ?? 0,
AnswerText5 = at.Field<int?>("-4") ?? 0,
Rank = qa.Field<Int64?>("Rank"),
Average = qa.Field<decimal?>("Average"),
N = inter.Field<int?>("N")
};