How to do a GroupBy statement with ServiceStack OrmLite - ormlite-servicestack

I am doing some queries for Data Visualization and rely on GroupBy, Avg, Sum, and similar functions to get a good dataset from the DB.
I would like to use something similar to GroupBy with ServiceStack OrmLite. On the ShippersExample page I see the following query. Is there an easier or better way to do this?
For example, I have a 'location' column and would like to find the top 5 locations of an entry, and list these locations with the amount of times it occurs. I only have 1 table, so no need for joins.
var rows = db.SqlList<ShipperTypeCount>(
"SELECT {0}, COUNT(*) AS Total
FROM Shippers
GROUP BY {0}
ORDER BY Total".Fmt("ShipperTypeId".SqlColumn()));

You can also use a SqlExpression, e.g:
var rows = db.SqlList<ShipperTypeCount>(
db.From<Shipper>()
.GroupBy(x => x.ShipperTypeId)
.OrderBy("Total")
.Select(x => new { x.ShipperTypeId, Total = Sql.As(Sql.Count("*"), "Total") }));
Alternatively instead of using a concrete POCO you can use a generic dictionary to populate a dictionary of ShipperTypeId => Total, e.g:
var q = db.From<Shipper>()
.GroupBy(x => x.ShipperTypeId)
.OrderBy("2")
.Select(x => new { x.ShipperTypeId, Total = Sql.Count("*") });
var results = db.Dictionary<int, int>(q);

Related

How to get count of certain record saved in Uppercase, lower or a combination using LINQ query

I need to get the count of IN / in / In from SoccerStatus regardless if the records are saved in upper case, lower case or a combination of both ie IN or in or In from SQLite database in Xamarin Forms. How can I achieve that ?
var count_in = (from x in conn.Table<SoccerAvailability>().Where(x => x.SoccerStatus == IN) select x).Count();
Use string.Equals and tell it to ignore case...
var count_in = (from x in conn.Table<SoccerAvailability>().Where(x => string.Equals(x.SoccerStatus, "IN", StringComparison.OrdinalIgnoreCase)) select x).Count();
EDIT: Per your comment I see that the Linq provider you're using doesn't support string.Equals. You can try the following which should be more portable but possibly a bit slower...
var count_in = (from x in conn.Table<SoccerAvailability>().Where(x => x.SoccerStatus.ToUpper() == "IN") select x).Count();

Crossfilter grouping filtered keys

I have some json, for examle:
data = {
"name":"Bob","age":"20",
"name":"Jo","age":"21",
"name":"Jo","age":"22",
"name":"Nick","age":"23"
}
Next, I use crossfilter, create dimension and filter it:
let ndx = crossfilter(data);
let dim = ndx.dimension(d => d.name).filter(d !== "Jo");
//try to get filtered values
let filtered = dim.top(Infinity); // -> return 2 values where 'name'!='Jo'
//"name":"Bob","age":"20"
//"name":"Nick","age":"23"
let myGroup = dim.group(d => {
if(d === 'Jo') {
//Why we come here? This values must be filtered already
}
})
How can I filter my dimension and don't have these values on 'dim.group'?
Not sure what version you are using, but in the current version of Crossfilter, when a new group is created all records are first added to the group and then filtered records are removed. So the group accessor will be run at least once for all records.
Why do we do this? Because for certain types of grouping logic, it is important for the group to "see" a full picture of all records that are in scope.
It is possible that the group accessor is run over all records (even filtered ones) anyway in order to build the group index, but I don't remember.

How to Group By on Columns in datatable in Linq

var res3 = dtPriorityMatrix.AsEnumerable()
.GroupBy(hour => hour.Field<int>("Hour"))
.OrderBy(item => item.Key)
.Select(item => new { Hour = item.Key });
I have a data table with 5 columns and around 200+ rows of data. One has hours (0-23) and others are Priority 1, Priority 2 and so on till Priority 4. I need to extract number of items of each priority for every hour. I need help with the Linq query as it is not my strong field. Thanks
You have to group by both columns. something like this
var query = source.GroupBy(x => new { x.Column1, x.Column2 });
so your code will be
var res3 = dtPriorityMatrix.AsEnumerable()
.GroupBy(hour =>new { hour= hour.Field<int>("Hour"), priority=hour.Field<int>("Priority")} )
.Select(item => new {count=item.count(), Hour = item.Key.hour, priority = item.Key.priority});\
edit
Reply to your comment:
when you have your results in a list, you can write it in anyway that you want.
the out put of the query is a list that contains hour, priority and count.
if you want it in 3 lines of string
string hLine="";
string pLine="";
string countLine="";
foreach(var item in res3)
{
hLine+= item.hour+" ";
pLine+= item.prioriy+" ";
countLine+= item.count+" ";
}
if you want to have them in a table or anything, use the same approach for filling your tables items

Convert SQL to LINQ query to get max

hi guys i am stuck converting below sql to LINQ query.
all i want is to have maximum number from list of (FA-00001 ,FA-00059)
SELECT MAX(CAST(SUBSTRING(ReferenceId, PATINDEX('%-%', ReferenceId) + 1, LEN(ReferenceId) - PATINDEX('%-%', ReferenceId)) AS int)) AS MaxReferenceId FROM [ClientRC].[dbo].[EHO_Action]
is this possible to convert to LINQ? thanks
An alternative approach using anonymous projection:
var y = (from record in
(from record in db.ClientRC
select new
{
Group = "x",
ReferenceNumber = Convert.ToInt32(record.ReferenceId.Split('-')[1])
})
group record by new { record.Group } into g
select new
{
MaxReferenceId = g.Max(p => p.ReferenceNumber)
});
http://msdn.microsoft.com/en-us/library/bb386972.aspx
var myvar = (from v in db.object where v!=null select v.id).Max();
MSDN has lots of examples for stuff like this.
Or, you can execute queries directly against a datacontext if you're using entity framework. Just make sure if you're doing anything with parameters you're parameterizing the query and not taking user input directly into it.
http://msdn.microsoft.com/en-us/library/ee358769.aspx
Try this..
var list = DBContext.EHO_Action
.Where(x => x.YourListColumn != null)
.Select(x => x.YourListColumn).ToList(); // Take the list (FA-00001 ,FA-00059) from db to a list
var maxNo = list.Max(x => Convert.ToInt32(x.Split('-')[1]));
Please change the context and column names according to your Linq context.
If you want to use sql you can do it this way..
var list = DBContext.ExecuteQuery<string>("select yourreqrdcolumn from [ClientRC].[dbo].[EHO_Action]");

Add Conditional Join Dynamically with Linq

I have a basic search control which lists companies from a CRM depending on predefined search/filtering criteria supplied by dropdowns. The default selection is "ALL" for each DropDown, otherwise the user chooses a specific item(s). I'd like to be able to construct a Linq query dynamically based on the selections. Out of the 5 selectors they supply values that I can match against the Company table, but two of the selectors (if either or both are chosen) would require a join or joins, else no action should be taken again the base result set. I hope this makes sense.
I'm not sure how to do this effectively. Here is my code:
private void Search()
{
EnergyPubsCRMDataContext dc = new EnergyPubsCRMDataContext();
var results = (from c in dc.Companies
select c);
//only create the join if the selected index > 0
if (ddlIndustry.SelectedIndex > 0)
{
//A company can be in 1 or more industries, thus here I want to join
//with the CompanyIndustry table and have a WHERE clause to match on the ddlIndustry.SelectedValue
}
//only create the join if the selected index > 0
if (ddlServices.SelectedIndex > 0)
{
//A company can offer 1 or more services. Here I want to join to the CompanyService table
//on the CompanyID and have a WHERE clause to match the ddlServices.SelectedValue
}
//These work OK to shape the overal query further (they don't need joins)
if (ddlCountry.SelectedIndex > 0)
results = results.Where(c => c.CountryID == Convert.ToInt32(ddlCountry.SelectedValue));
if (ddlStateRegion.SelectedIndex > 0)
results = results.Where(c => c.StateRegionID == Convert.ToInt32(ddlStateRegion.SelectedValue));
if (ddlAccountManagers.SelectedIndex > 0)
{
Guid g = new Guid(ddlAccountManagers.SelectedValue);
results = results.Where(c => c.UserId == g);
}
results = results.OrderBy(c => c.CompanyName);
//Bind to Grid....
}
if (ddlIndustry.SelectedIndex > 0)
{
//A company can be in 1 or more industries, thus here I want to join
//with the CompanyIndustry table and have a WHERE clause to match on the ddlIndustry.SelectedValue
results = results.Where(c => c.CompanyIndustry.IndustryID == ddlIndustry.SelectedValue);
}
Assuming you have correct foreign keys in your database/DBML.
This will generate the join implicitly.
I had very similar issue and no foreign keys I could leverage.
My solution would translate to something like this:
results = results
.Join(dc.CompanyIndustry, c => c.CompanyID, ci => ci.CompanyID, (c, ci) => new { c, ci.IndustryID })
.Where (a => a.IndustryID == ddlIndustry.SelectedValue)
.Select(a => a.c);
Basically:
1) first we create a join, with a projection that gives us IndustryID (join)
2) we filter based on IndustryID (where)
3) we return original anonymous type, so that we can modify original query (select)

Resources