How do I sort this? - sorting

Here is a data dump of what I am trying to sort
array
1
struct
col 1
dataid 48
identifier 1
row 1
size_x 4
size_y 1
2
struct
col 1
dataid 42
identifier 2
row 2
size_x 2
size_y 1
3
struct
col 3
dataid 45
identifier 3
row 2
size_x 2
size_y 1
I want to sort by row first, then col. Lots of examples how to sort by one data element, but none that talk about secondary elements.

ColdFusion 10 has built-in customised array sorting using a callback. The docs for arraySort() didn't mention this, but I've just updated them with an example. My example there doesn't show a compound sort like you require, but it's easy enough:
<cfscript>
comparator = function(e1, e2){
e1.row += 0; // need to make sure it's not a string for the Java method call below
var rowCompare = e1.row.compareTo(e2.row + 0);
if (rowCompare !=0){
return rowCompare;
}
e1.col += 0;
return e1.col.compareTo(e2.col + 0);
};
data = [
{row=3, col=3}, {row=3,col=2}, {row=3, col=1},
{row=2, col=3}, {row=2,col=2}, {row=2, col=1},
{row=1, col=3}, {row=1,col=2}, {row=1, col=1}
];
writeDump(var=data);
arraySort(data, comparator);
writeDump(var=data);
</cfscript>
This leverages that CF numerics are java.lang.Double objects.

<cfscript>
//ColdFusion 10 only supports this new types of struct declaration
recordArr = [
{col: 1,dataid:48,identifier:1,row:1,size_x:4,size_y:1},
{col: 1,dataid:42,identifier:2,row:2,size_x:2,size_y:1},
{col: 3,dataid:45,identifier:3,row:2,size_x:2,size_y:1}
];
//ColdFusion 10 only supports this new queryNew() functionality
queryObj = queryNew("col,dataid,identifier,row,size_x,size_y",
"Integer,Integer,Integer,Integer,Integer,Integer",
recordArr);
</cfscript>
<!--- Here it comes our favourite cfquery tag. We can apply order by clause
as per our wish --->
<cfquery name="ordredResult" dbtype="query">
SELECT * FROM queryObj ORDER BY row ASC, col ASC
</cfquery>
<!--- Here is the expected result --->
<cfdump var="#ordredResult#">

Related

DAX: Weighted Average on Different Level of Aggregation using Netted Summarized Table

I have the following test Data set, with 3 different levels of grouping. And I want to make a measure "Value WA" for Value, and the make a matrix like showing in the image after. Basically, it is the weighted average of "Value" based on "Market Value“ for the sub-categories contained in it. If it is on row of "Portfolio1", it is the WA of Index1 and Index2, and if it is on row of "Class1", it is the WA of "Portfolio1" and "Portfolio2" etc.
I had the code for measure "Value WA" at the bottom using netted SUMMARIZE. But somehow it doesn't work appropriately. I can't figure out why, but I guess it is on the last line of "RETURN SUMX(SubTable2, [Value2] * [WT2])"
Please help me with the correct approach. Thank you very much!
Date set
GroupLevel1
GroupLevel2
GroupLevel3
Market Value
Value
Class1
Portfolio1
Index1
30
3
Class1
Portfolio1
Index2
30
2
Class1
Portfolio1
Index8
30
4
Class1
Portfolio2
Index3
50
4
Class2
Portfolio3
Index4
50
6
Class2
Portfolio4
Index5
50
4
Class3
Portfolio5
Index6
200
5
Class3
Portfolio5
Index7
200
1
what I want it to look like:
Value WA =
IF( ISFILTERED('Table'[GroupLevel3]),
CALCULATE(SUM('Table'[Value])),
VAR SubTable1 =
ADDCOLUMNS(
SUMMARIZE('Table','Table'[GroupLevel3],'Table'[GroupLevel2],'Table'[GroupLevel1]),
"WT3", CALCULATE(SUM('Table'[Market Value])) /
CALCULATE(SUM('Table'[Market Value]),
ALL('Table'[GroupLevel3])),
"Value3", CALCULATE(SUM('Table'[Value])))
VAR Val_level2 = SUMX(SubTable1, [Value3] * [WT3])
RETURN
IF( ISFILTERED('Table'[GroupLevel2]),
Val_level2,
VAR SubTable2 = ADDCOLUMNS(
SUMMARIZE(SubTable1,[GroupLevel2]),
"WT2", CALCULATE(SUM('Table'[Market Value])) /
CALCULATE(SUM('Table'[Market Value]),
ALL('Table'[GroupLevel2])),
"Value2", Val_level2)
RETURN SUMX(SubTable2, [Value2] * [WT2])
)
)

Unable to check if a list of int is completely contained in another int list

I have a list of int that represents service ids. and I want to make sure that all of those ids exist in the database.
In other words , I want to scan the list of ids and the table of services to make sure that all of these ids exist in the database.
I tried this :
List<int> ids;//[1,52]
var x = _context.Services.Any(s => ids.Contains(s.Id));//service ids = [1,2,3]
but it returned True , which is not the desired output.
I've also tried it this way :
_context.Services.Any(s => ids.Any(id => id == s.Id)!=null);
and this way
_context.Services.Any(s => ids.Any(id => id == s.Id)!=null);
with no luck as well. what is the right way to do it? I'm using EFCore 3.1.8
Normally you would use Queryable.Except for this.
If you have two sequence of items, and you do A except B, then if you have nothing left, then apparently every item from A is also an item in B.
IEnumerable<int> requiredIds = ...
IQueryable<int> serviceIds = dbContext.Services.Select(service => service.Id);
bool someRequiredIdsMissing = requiredIds.Except(serviceIds).Any();
Alas, your A is local and your B is in the database. So I guess this won't work.
What you can do, is to keep only Service Ids that are in the list of required Ids, and count them. If there are less, then apparently some requiredIds are not in serviceIds.
var requiredServiceIds = serviceIds.Where(serviceId => requiredIds.Contains(serviceId);
bool allRequiredAvailale = requiredServiceIds.Count() != requiredIds.Count();
Example:
IEnumerable<int> requiredIds = new [] {1, 2, 7, 20};
Total: 4 elements
Your service Ids are: 1 2 4 5 8 20 25
requiredServiceIds : 1 2 20: total 3 elements
So allRequiredAvailale is false;
Example 2:
Your service Ids are: 1 2 4 5 7 8 20 25
requiredServiceIds : 1 2 7 20: total 4 elements
So allRequiredAvailale is true;

LINQ query for Group by a key and then order by different column

i want to display countof records based on grouping by the id and name then i want to order them in their descending order of display.
My database structure is as follows:-
rowid id name viewedon viewedby
1 a1 reporter 23/07/2014 a#yahoo.com
2 a2 teacher 24/07/2014 test#gmail.com
3 a1 reporter 24/07/2014 wayne#zz.com
4 a2 teacher 24/07/2014 asdasd#zz.com
5 a1 reporter 24/07/2014 btttt#zz.com
6 a3 driver 26/02/2014 sfdf#yahoo.com
7 a4 operator 3/3/1991 asds#asd.com
8 a2 teacher 2/9/2011 tsdasd#gmail.com
9 a1 reporter 3/5/1992 asdas#fg.com
10 a4 operator 12/12/2005 asdss#a.com
11 a1 reporter 2/2/2002 as#as.com
12 a3 driver 10/7/2015 asdas#as.com
my Query is as follows
var q=from j in context.item
group jobs by new { j.Id, j.Name } into gr
select new DAO<String>
{
Key = gr.Key.Name,
Count = gr.Count()
}).OrderByDescending(k => k.Count).Take(5).ToList();
This is giving correct result as follows:-
key count
reporter 5
teacher 3
operator 2
driver 2
reporter and teacher has high views so their count and order is justified .
now i have problem with this result. operator and driver has same view count but since driver has latest viewon date so it should come before driver.
so my result should be.
reporter 5
teacher 3
driver 2
operator 2
what should be my LINQ to achieve this result
You need to select the column for ordering. You can try this way :
var q = (from j in context.item
group jobs by new { j.Id, j.Name } into gr
select new
{
Key = gr.Key.Name,
Count = gr.Count(),
LastViewedOn = gr.Max(o => o.viewedon)
}).OrderByDescending(k => k.Count).ThenByDescending(o => o.LastViewedOn)
.Select(o => new DAO<String>
{
Key = o.Key,
Count = o.Count
})
.Take(5).ToList();

How to select row index along with its elements of a list?

I have a list of following class:
Class Test
{
int A;
String B;
Char C;
}
List<Test> obj:
10 “Abc” 'a'
29 “Bcd” 'b'
36 “Cde” 'c'
45 “Def” 'd'
51 “Efg” 'e'
I want a linq Query that will give me output like this:
1 “Abc”
2 “Bcd”
3 “Cde”
4 “Def”
5 “Efg”
You can use new with an anonymous class to obtain a projection; use the override of Select that gives you the item number to produce the row number, like this:
var projection = obj.Select((o,i) => new {Index = i+1, Value=B});
foreach (var item in projection) {
Console.WriteLine("{0} “{1}”", item.Index, item.Value);
}

Is a dynamic pivot using LINQ possible?

I have a T-SQL 2005 query which returns:
pid propertyid displayname value
----------- ----------- --------------- ---------------
14270790 74 Low Price 1.3614
14270790 75 High Price 0
14270791 74 Low Price 1.3525
14270791 75 High Price 0
14270792 74 Low Price 1.353
14270792 75 High Price 0
14270793 74 Low Price 1.3625
14270793 75 High Price 0
14270794 74 Low Price 1.3524
14270794 75 High Price 0
What I would like to do is essentially pivot on the displayname field, hopefully producing:
pid Low Price High Price
14270790 1.3614 0
14270791 1.3525 0
14270792 1.353 0
14270793 1.3625 0
14270794 1.3524 0
(Not sure how the propertyid field would be output, so I left it out (was hoping it would simply sit alongside the Low Price and High Price fields, to indicate their IDs, but I don't think that will work.)
The problem is that the content of the original displayname field is dynamic - it is produced from a join with a PropertyName' table, so the number of pivoted columns is variable. It could therefore containHigh Price,Low Price,OpenandClose`, depending on what the join with that table returns.
It is, of course, relatively easy (regardless of the trouble I'm having writing the initial query!) to produce this pivot in a fixed query or stored proc. However, is it possible to get LINQ to generate a SQL query which would name each column to be produced rather than having to write a dynamic (probably in a stored proc) query which lists out the column names?
Thanks,
Matt.
I'll give you a sample with a different data (that I needed). You can adapt that to your need. Note only two linq queries are used, most of the other fluff is to convert a list into a datatable.
var data = new[] {
new{Student=1, Subject="English", Marks=40},
new{Student=1, Subject="Maths", Marks=50},
new{Student=1, Subject="Science", Marks=60},
new{Student=1, Subject="Physics", Marks=70},
new{Student=1, Subject="Chemistry", Marks=80},
new{Student=1, Subject="Biology", Marks=90},
new{Student=2, Subject="English", Marks=4},
new{Student=2, Subject="Maths", Marks=5},
new{Student=2, Subject="Science", Marks=6},
new{Student=2, Subject="Physics", Marks=7},
new{Student=2, Subject="Chemistry", Marks=8},
new{Student=2, Subject="Biology", Marks=9}
};
/*Here the pivot column is the subject and the static column is student
group the data against the static column(s)*/
var groups = from d in data
group d by d.Student into grp
select new
{
StudentId = grp.Key,
Marks = grp.Select(d2 => new { d2.Subject, d2.Marks }).ToArray()
};
/*get all possible subjects into a separate group*/
var subjects = (from d in data
select d.Subject).Distinct();
DataTable dt = new DataTable();
/*for static cols*/
dt.Columns.Add("STUDENT_ID");
/*for dynamic cols*/
foreach (var subject in subjects)
{
dt.Columns.Add(subject.ToString());
}
/*pivot the data into a new datatable*/
foreach (var g in groups)
{
DataRow dr = dt.NewRow();
dr["STUDENT_ID"] = g.StudentId;
foreach (var mark in g.Marks)
{
dr[mark.Subject] = mark.Marks;
}
dt.Rows.Add(dr);
}
This is the closest I could get, but it's not LINQ...
create table #t
(
pointid [int],
doublevalue [float],
title [nvarchar](50)
)
insert into #t
select
distinct top 100
v.pointid, v.doublevalue, p.title
from [property] p
inner join pointvalue v on p.propertyid = v.propertyid
inner join point pt on v.pointid = pt.pointid
where v.pointid in (select top 5 p.pointid from point p where p.instanceid = 36132)
declare #fields nvarchar(250)
set #fields = (select STUFF((SELECT N',[' + title + ']' FROM [property] FOR XML PATH('')), 1, 1, N''))
--select #fields
declare #sql nvarchar(500)
set #sql = 'select * from #t
pivot
(
sum(doublevalue)
for [title] in ('+#fields+')
) as alias'
--select #sql
exec (#sql)
drop table #t
The kicker is that I'm simply asking for every entry in the Property table, meaning there's a lot of columns, in the resulting pivot, which have NULL values.
the code I think is like this:
var list = from table in Property
group table by table.pid into g
select new
{
pid = g.key,
LowPrice = g.Where(w => w.pid== g.key && w.priceType == "low").Select(s => s.value).FirstorDefault(),
HighPrice = g.Where(w => w.pid== g.key && w.priceType == "high").Select(s => s.value).FirstorDefault(),
};
Hope it can help you and have a nice day.

Resources