How to convert SQL Query into LinQ - sql-server

I'm new to SQL, please Help me how to convert this query into LinQ
This is My Table Dept:
Id Name Sal Department
1 John 40000 Dotnet
2 mick 45000 DotNet
3 Pillay 777 Sql
Here I want to display Salary Based On Department Name, like:
DepartmentName ToalSal
Dotnet 85000
Sql 777
select DeprtmentName,sum(sal) from Dept_Emp Group by DeprtmentName
I wrote some Part of query
public IEnumerable<Dept_Emp> GetJam()
{
var x = from n in db.Dept_Emp
group n by n.Sal into g
select new
{
DeprtmentName = g.Key
};
// what I mention Here;
}

You are missing calculating sum of sal fields of grouped entities. Also you are grouping by wrong field. You should use department name for grouping
from de in db.Dept_Emp
group de by de.DeprtmentName into g
select new {
DepartmentName = g.Key,
TotalSalary = g.Sum(x => x.Sal) // aggregation here
}
What you have as output is anonymous objects. You cannot return them directly from method. You have several options here
Create custom class like DepartmentTotals with name and total salary fields, and return instances of this class instead of anonymous objects. Then return type will be IEnumerable<DepartmentTotals>.
Create Tuple<string, int> (or whatever type of salary). And return such tuples.
Use C# 7 tuples.

Related

Multiple AggregateResult Querys

Hi guys,
I'm currently trying to join two objects in a same query or result.
My question is if it's possible to show or debug the sum of FIELD A FROM LEAD + sum of FIELD B FROM two different Objects.
Here's an example I'm working on:
Btw I really appreciate your time and comments, and if i'm making a mistake pls let me know, thank you.
public static void example() {
String sQueryOne;
String sQueryTwo;
AggregateResult[] objOne;
AggregateResult[] objTwo;
//I tried to save the following querys into a sObject List
List<SObject> bothObjects = new List<SObject>();
sQueryOne = 'Select Count(Id) records, Sum(FieldA) fieldNA From Lead';
objOne = Database.query(sQueryOne);
sQueryTwo = 'Select Count(Id) records, Sum(FieldA) fieldNB From Opportunity';
objTwo = Database.query(sQueryTwo);
bothObjects.addAll(objOne);
bothObjects.addAll(objTwo);
for(sObject totalRec : bothObjects) {
//There's a Wrapper(className) I created which contains some variables(totalSum)
className finalRes = new className();
finalRes.totalSum = (Integer.valueOf(fieldNA)) + (Integer.valueOf(fieldNB));
System.debug('The sum is: '+finalRes.totalSum);
For example if I call a System debug with the previous variable finalRes.totalSum it's just showing the first value(fieldNA) duplicated.
The following debug shows the current values of the sObject List which I want to sum for example FIELD0 = from leads, FIELD0 = from Opportunities.
}
}
You access the columns in AggregateResult by calling get('columnAlias'). If you didn't specify an alias they'll be autonumbered by SF as expr0, expr1... When in doubt you can always go System.debug(results);
Some more info: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_SOQL_agg_fns.htm
This might give you some ideas:
List<AggregateResult> results = new List<AggregateResult>{
[SELECT COUNT(Id) records, SUM(NumberOfEmployees) fieldA, SUM(AnnualRevenue) fieldB FROM Account],
[SELECT COUNT(Id) records, SUM(Amount) fieldA, SUM(TotalOpportunityQuantity) fieldB FROM Opportunity],
[SELECT COUNT(Id) records, SUM(NumberOfEmployees) fieldA, SUM(AnnualRevenue) fieldB FROM Lead]
/* hey, not my fault these are only 2 standard numeric fields on Lead.
It doesn't matter that they're identical to Account fields, what matters is what their SUM(...) aliases are
*/
};
List<Decimal> totals = new List<Decimal>{0,0,0};
for(AggregateResult ar : results){
totals[0] += (Decimal) ar.get('records');
totals[1] += (Decimal) ar.get('fieldA');
totals[2] += (Decimal) ar.get('fieldB');
}
System.debug(totals); // (636, 8875206.0, 9819762558.0) in my dev org
(I'm not saying it's perfect, your wrapper class sounds like better idea or maybe even Map<String, Decimal>. Depends what are you going to do with the results)

SQL Query Parent Child Full Path from table

I have a table listing the parent child relationship for each element like this:
ParentID ParentTitle ChildId ChildTitle
----------------------------------------------
843 Documents 38737 Jobs
843 Documents 52537 Tools
843 Documents 5763 SecondOps
843 Documents 4651 Materials
38737 Jobs 16619 Job001
38737 Jobs 16620 Job002
38737 Jobs 16621 Job003
38737 Jobs 16622 Job004
38737 Jobs 16623 Job005
52537 Tools 1952 HandTools
52537 Tools 1953 Automated
52537 Tools 1957 Custom
1952 HandTools 12 Cordless10mm
1952 HandTools 13 Cordless8mm
1952 HandTools 14 CableCrimp
1952 HandTools 15 Cutter
1952 HandTools 16 EdgePlane
5763 SecondOps 101 Procedure001
5763 SecondOps 102 Procedure002
5763 SecondOps 103 Procedure003
4651 Materials 33576 Raw
4651 Materials 33577 Mixed
4651 Materials 33578 Hybrid
4651 Materials 33579 Custom
16622 Job004 101 Procedure001
16622 Job004 14 CableCrimp
16622 Job004 15 Cutter
16622 Job004 4651 Mixed
16623 Job005 102 Procedure002
16623 Job005 103 Procedure003
16623 Job005 16619 Job001
16623 Job005 1953 Automated
16623 Job005 33579 Custom
16623 Job005 33576 Raw
I would like to get the full path of each Combination using the IDs, for example
Documents\Jobs\Job003 = 843\38737\16621
Another example would be "Procedure001" which is listed in 2 places
Documents\SecondOps\Procedure001 = 843\5763\101
The same document is also referenced here:
Documents\Jobs\Job004\Procedure001 = 843\38737\16622\101
I'd like to take this table and build a TreeView in .NET. So having the full path for each item would make it a cake walk.
Otherwise, I was thinking that I could start at the Root page and keep recursing through the parents, building a child list, then recursing those, etc.
Is there a better way to query this to build those paths? This list has 400,000 records so if there is a more efficient way it would save time
This was all originally in an AS400 system DB until 2000ish then made into a MediaWiki site. I am pulling the data via the api with the intent of building an interface for a SQL Server database.
I can do basic SQL queries, joins, unions, etc.
Let me know what other info I can provide if this isn't clear
You could use INNER JOIN and LEFT JOIN if you are using SQL SERVER MS, and here are how the query look like, which will give you the full result (combination) based on your requirement:
SELECT A.ParentTitle + '\'+B.ParentTitle+
CASE WHEN C.ParentTitle IS NOT NULL THEN '\' +C.ParentTitle
ELSE ''
END
+
' =' + A.ParentID + '\'+B.ParentID+
CASE WHEN C.ParentID IS NOT NULL THEN '\' +C.ParentID
ELSE ''
END
FROM TABLE AS A
INNER JOIN TABLE AS B
ON B.ParentID = A.ChildId
LEFT JOIN TABLE AS C
ON C.ParentID = B.ChildId
Not 100% sure whether it will work as I expected or not, please give it a try xD
A tree structure means Recursion for a generic solution.
Pls, don't try this in sql. Just take datarow from sql into a list or something like and make populate with recursion in a programming language.
Your tree class wil be like :
public class MyObj {
public int Id {get; set;}
public string Title {get; set;}
public List<MyObj> {get; set; } = null;
}
0.You table its pretty wrong. The corect way will be :
CREATE TABLE Jobs(
Id int not null primary key,
Title nvarchar(255) not null,
StartTime datetime,--optional maybe will help
ParentId int null --can be null root will have no parent
)
But I will try to explain on your table how it's done.
I will suppose that you have some kind datacontext (DBML,EDMX etc.)
Find root or roots. In your case root will those nr that are on ParentID and are not on the ChildId.
Query that will list your roots:
SELECT DISTINCT a.ParentId FROM
YourTable a LEFT JOIN
YourTable b ON a.ParentId=b.ChildId
WHERE b.ParentId is null
Make a recursive procedure that will retrive your data in a class structure as above(MyObj).
procedure MyObj GetTree(int id, db){
if (db.YourTable.Any(r => r.ParentId==Id)){
var q=db.YourTable.Select(r => r.ParentId==Id).ToList();
var result = new MyObj{
Id = q.ParentId,
Title = q.ParentTitle,
Children = new List<MyObj>()
}
foreach( var el in q) {
if (db.YourTable.Any(r => r.ParentId==el.ChildId))
result.Children.Add(GetTree(el.ChildId,db))
else
result.Children.Add( new MyObj{
Id = el.ChildId,
Title = el.ChildTitle,
Children = null
});
return result;
}
}
return null;
}
make trees with list Id from point 1 stored in a list let's say ListIds you will do something like that:
List finaltrees = new List()
Ids.ForEach(id => finaltrees.Add(GetTree(id,dbcontext));
Now you have a tree structure in finaltrees.
PS:
I wrote the code directly in browser (C#),there can be some typos error.
So to elaborate on what I am trying to do, I'm working with a wiki version that doesn't use namespaces to establish document paths.
For example if a page is 3 levels deep on a document tree like this
RootPage
Page01
Page02
Page03
Page04
Using the Namespace approach Page03's Name(Path) is "RootPage:Page01:Page02:Page03"
I would Like to do the same thing with the PageIDs
So given this example you would have
PageTitle PageId Path
RootPage 001 001
Page01 101 001:101
Page02 201 001:101:201
Page03 301 001:101:201:301
Page04 302 001:101:201:302
So now All I have to do is Put the PagePath together.
There are several challenges to Consider with this wiki
No 2 documents can have the same TITLE
Document IDs are basically
irrelevant, but handy in this case(at least in the version I am
working on)
Thankfully there is a list of Pages and their "Links" or
Child Pages. I believe you would call it a MANY to MANY
The Key Point to remember is even if a page is listed as a child of many other pages, Only one really exists and I only need one of them in the results.
So Using LONG's example here is where I've gotten to
Using this Table:
CREATE Table [dbo].[ExampleTable](
[RecordID] Int IDENTITY (1, 1) Not NULL,
[ParentID] Int Not NULL,
[ParentTitle] VARCHAR(800) NULL,
[ChildID] Int Not NULL,
[ChildTitle] VARCHAR(800) NULL,
PRIMARY KEY CLUSTERED ([RecordID] ASC),);
This Data:
INSERT INTO [dbo].[ExampleTable]
([ParentID]
,[ParentTitle]
,[ChildID]
,[ChildTitle])
VALUES
(843,'Documents',38737,'Jobs'),
(843,'Documents',52537,'Tools'),
(843,'Documents',5763,'SecondOps'),
(843,'Documents',4651,'Materials'),
(38737,'Jobs',16619,'Job001'),
(38737,'Jobs',16620,'Job002'),
(38737,'Jobs',16621,'Job003'),
(38737,'Jobs',16622,'Job004'),
(38737,'Jobs',16623,'Job005'),
(52537,'Tools',1952,'HandTools'),
(52537,'Tools',1953,'Automated'),
(52537,'Tools',1957,'Custom'),
(1952,'HandTools',12,'Cordless10mm'),
(1952,'HandTools',13,'Cordless8mm'),
(1952,'HandTools',14,'CableCrimp'),
(1952,'HandTools',15,'Cutter'),
(1952,'HandTools',16,'EdgePlane'),
(5763,'SecondOps',101,'Procedure001'),
(5763,'SecondOps',102,'Procedure002'),
(5763,'SecondOps',103,'Procedure003'),
(4651,'Materials',33576,'Raw'),
(4651,'Materials',33577,'Mixed'),
(4651,'Materials',33578,'Hybrid'),
(4651,'Materials',33579,'Custom'),
(16622,'Job004',101,'Procedure001'),
(16622,'Job004',14,'CableCrimp'),
(16622,'Job004',15,'Cutter'),
(16622,'Job004',4651,'Mixed'),
(16623,'Job005',102,'Procedure002'),
(16623,'Job005',103,'Procedure003'),
(16623,'Job005',16619,'Job001'),
(16623,'Job005',1953,'Automated'),
(16623,'Job005',33579,'Custom'),
(16623,'Job005',33576,'Raw')
GO
And This Query, Which I modified from LONG's example:
SELECT DISTINCT C.ChildTitle as PageTitle, convert(varchar(20),A.ParentID) + ':' + convert(varchar(20),B.ParentID) +
CASE WHEN C.ParentID IS NOT NULL THEN ':' + convert(varchar(20),C.ParentID)
ELSE ''
END
+
CASE WHEN C.ChildID IS NOT NULL THEN ':' + convert(varchar(20),C.ChildID)
ELSE ''
END
FROM ExampleTable AS A
INNER JOIN ExampleTable AS B
ON B.ParentID = A.ChildId
LEFT JOIN ExampleTable AS C
ON C.ParentID = B.ChildId
ORDER By PageTitle
I get These Results:
PageTitle UnNamed
NULL 16622:4651
NULL 38737:16622
NULL 38737:16623
NULL 52537:1952
NULL 843:38737
NULL 843:4651
NULL 843:52537
NULL 843:5763
Automated 843:38737:16623:1953
CableCrimp 843:38737:16622:14
CableCrimp 843:52537:1952:14
Cordless10mm 843:52537:1952:12
Cordless8mm 843:52537:1952:13
Custom 38737:16622:4651:33579
Custom 843:38737:16623:33579
Cutter 843:38737:16622:15
Cutter 843:52537:1952:15
EdgePlane 843:52537:1952:16
Hybrid 38737:16622:4651:33578
Job001 843:38737:16623:16619
Mixed 38737:16622:4651:33577
Mixed 843:38737:16622:4651
Procedure001 843:38737:16622:101
Procedure002 843:38737:16623:102
Procedure003 843:38737:16623:103
Raw 38737:16622:4651:33576
Raw 843:38737:16623:33576
What I'd like to get is a SINGLE occurance of each page, Regarless of which Parent it happens to be found
Then I can use these Paths to turn the Virtual Tree Structure into an actual Tree Structure.
The Last Issue is that the actual Link List is VERY similar to the example I created, except that it has 400,000 records.
When I run this query against the actual "Link List" it runs for about 17 minutes and runs out of memory.
I've been researching the MAXRECURSION option, but I am still working on it, don't know if that is problem or not.

Modeling a non-primary Key relationship

I am trying to model the following relationship with the intent of designing classes for EF code first.
Program table:
ProgramID - PK
ProgramName
ClusterCode
Sample data
ProgramID ProgramName ClusterCode
--------------------------------------
1 Spring A
2 Fall A
3 Winter B
4 Summer B
Cluster table:
ID
ClusterCode
ClusterDetails
Sample data:
ID ClusterCode ClusterDetails
---------------------------------
1 A 10
2 A 20
3 A 30
4 B 20
5 B 40
I need to join the Program table to the Cluster table so I can get the list of cluster details for each program.
The SQL would be
Select
from Programs P
Join Cluster C On P.ClusterCode = C.ClusterCode
Where P.ProgramID = 'xxx'
Note that for the Program table, ClusteCode is not unique.
For Cluster table, neither ClusterCode nor ClusterDetail is unique.
How would I model this so I can take advantage of navigation properties and code-first?
assuming you have mapped above two tables and make an association between them and you are using C#, you can use a simple join :
List<Sting> clustedDets=new ArrayList<String>();
var q =
from p in ClusterTable
join c in Program on p equals c.ClusterTable
select new { p.ClusterDetails };
foreach (var v in q)
{
clustedDets.Add(v.ClusterDetails);
}

Using Yii ActiveRecord to do the following query

I have a table which I would like to get all the points as SUM() for a single user_id
e.g
tblPoints
user_id points
111 50
111 100
111 100
How would I use the $criteria = new CDbCriteria() function to get the SUM(points) for the user_id of '111' - with the result being 250.
So far I have this... how would I make add SUM clause?
$Criteria = new CDbCriteria();
$Criteria->condition = "user_id = 2342312";
$Products = ShopPurchases::model()->find($Criteria);
$criteria->select = array('*', 'SUM(points) as pointsSum');
Need to define $pointsSum as a public property in your model and use:
$Products->pointsSum

SUM and DISTINCT of two different columns

I have a table Employee with say the following records
EmpID Salary Date
10 2000 1/1/2011
10 2000 2/1/2011
20 2000 1/1/2011
I want to count the total number of employees and the total salary (based on some other parameters)
Is there a easy way to write the following SQL query in entity framework.
select Sum(Salary), count(distinct(EmployeeID)) from empdb.employeesalary (where clause)
Have a class into which I need to select these values
class EmployeeEntity
{
decimal TotalAmount;
int EmployeeCount
}
I currently do two queries in EF as follows
objectcontext.employeesalary.Sum(c => c.Salary);
objectcontext.employeesalary.Select(c => c.EmployeeID).Distinct().Count();
How can I merge these into a single statement using Entity Framework. Am I missing something here.
Try something like this:
objectcontext.employeesalary
.Where(c => ...)
.GroupBy(_ => default(string))
.Select(g => new
{
Sum = g.Sum(c => c.Salary),
Count = g.Select(c => c.EmployeeID).Distinct().Count()
});
how about this ? you can merge your result of EF into your Employee Entity Class
var q = from f in objectcontext.employeesalary
where [clause]
group f by f.EmpID into g
select new EmployeeEntity
{
TotalAmount = g.Sum(c => c.Salary),
EmpmloyeeCount = g.Select(c => c.EmployeeID).Discinct().Count()
}
var EmployeeSummary = new List<EmployeeEntity>(q.ToList());

Resources