How can I achieve SQL Pivot statement from LINQ - sql

I am looking to achieve below SQL statement from LINQ. I am not sure whether is it possible? Can someone advice me on this?
SELECT *
FROM (
SELECT CONVERT(VARCHAR, (DATEADD(WEEK, DATEDIFF(WEEK, 0, S.SampleDrawn), 0)), 101) [Date], [Range] =
CASE
WHEN ProbBacteremia >= 0 AND ProbBacteremia < 0.50 THEN 'Low'
WHEN ProbBacteremia >= 0.50 AND ProbBacteremia < 0.75 THEN 'Med'
ELSE 'High'
END
FROM Result.Calculation C INNER JOIN Data.SampleSet S ON C.SampleSetID = S.ID WHERE S.SampleDrawn >= DATEADD(WEEK,-1,GETDATE())) o
PIVOT
(
COUNT(o.[Range])
FOR [Range] IN (
[Low], [Med], [High])
) pt
ORDER BY [Date]
Result of the above query will be as below
Date Low Med High
09/04/2017 370 174 175
09/11/2017 764 352 389
09/18/2017 759 384 360
09/25/2017 765 385 404
10/02/2017 115 48 56
Note that, above date has grouped by week. Ie. 09/04 , 09/11, 09/18 etc. I did lot of research but i found only to group by Week Number.
This is as far as i could come up with LINQ which will return me the below result set.
data = (from a in context.Calculations
where a.SampleSet.SampleDrawn >= dtStart && (isDeptFilter || a.SampleSet.Department == location)
group a by new { Text = RangeProvider(a.ProbBacteremia * 100, riskCats), Date = a.SampleSet.SampleDrawn.Date } into groupedData
orderby groupedData.Key.Date ascending
select new { Value = groupedData.Count(), Text = groupedData.Key.Text, Date = groupedData.Key.Date.ToShortDateString() }).ToList();
public static string RangeProvider(int value)
{
if (value > 0 && value <= 25)
{ return "Low"; }
if (value > 25 && value <= 75)
{ return "Medium"; }
if (value > 75 && value <= 90)
{ return "High"; }
else
{ return "Very High"; }
}
Result dataset of the obver LINQ is
Date Text Value
09/04/2017 Low 65
09/04/2017 Med 80
09/04/2017 High 40
09/05/2017 Low 30
10/05/2017 Med 50
10/05/2017 High 44
Hope this explains what I'm trying to achieve. Please can someone help me with this?

Well as a work-around i have used the Entity Framework Core's "FromSQL" method to execute my stored procedure which take cares of all the GROUP BY's.

you can use this.
data = (from a in context.Calculations
where a.SampleSet.SampleDrawn >= dtStart && (isDeptFilter || a.SampleSet.Department == location)
group a by new { Text = RangeProvider(a.ProbBacteremia * 100, riskCats), Date = a.SampleSet.SampleDrawn.Date } into groupedData
orderby groupedData.Key.Date ascending
select new {
Date = groupedData.Key.Date.ToShortDateString() ,
Low = ( groupedData.Key.Text =="Low" )?groupedData.Count() : 0,
Medium = ( groupedData.Key.Text =="Medium" )?groupedData.Count() : 0,
High = ( groupedData.Key.Text =="High" )?groupedData.Count() : 0,
VeryHigh = ( groupedData.Key.Text =="Very High" )?groupedData.Count() : 0
}).ToList();

Related

Power BI DAX - find repeatability

Given data as such:
Month ValueA
1 T
2 T
3 T
4 F
Is there a way to make a measure that would find if for each month, last three Values were True?
So the output would be (F,F,T,F)?
That would propably mean that my actual problem is solvable, which is finding from:
Month ValueA ValueB ValueC
1 T F T
2 T T T
3 T T T
4 F T F
the count of those booleans for each row, so the output would be (0,0,2[A and C],1[B])
EDIT:
Okay, I managed to solve the first part with this:
Previous =
VAR PreviousDate =
MAXX(
FILTER(
ALL( 'Table' ),
EARLIER( 'Table'[Month] ) > 'Table'[Month]
),
'Table'[Month]
)
VAR PreviousDate2 =
MAXX(
FILTER(
ALL( 'Table' ),
EARLIER( 'Table'[Month] ) - 1 > 'Table'[Month]
),
'Table'[Month]
)
RETURN
IF(
CALCULATE(
MAX( 'Table'[Value] ),
FILTER(
'Table',
'Table'[Month] = PreviousDate
)
) = "T"
&& CALCULATE(
MAX( 'Table'[Value] ),
FILTER(
'Table',
'Table'[Month] = PreviousDate2
)
) = "T"
&& 'Table'[Value] = "T",
TRUE,
FALSE
)
But is there a way to use it with unknown number of columns?
Without hard - coding every column name? Like a loop or something.
I would redo the data table in power query (upivoting the ValueX-columns) and changing T/F to 1/0. Then have a dim table with a relationship to Month, like this:
Then add a measure like this:
Three Consec T =
var maxMonth = MAX('Data'[Month])
var tempTab =
FILTER(
dimMonth;
'dimMonth'[MonthNumber] <= maxMonth && 'dimMonth'[MonthNumber] > maxMonth -3
)
var sumMonth =
MAXX(
'dimMonth';
CALCULATE(
SUM('Data'[OneOrZero]);
tempTab
)
)
return
IF(
sumMonth >= 3;
"3 months in a row";
"No"
)
Then I can have a visual like this when the slicer indicates which time window I'm looking at and the table shows if there has been 3 consecutive Ts or not.

How to query Oracle grouping?

I have such a problem and I don't know how to solve it, can you help me? t
The query returns a result that is shown on the photo and I want to get it to be shown in one line instead of many based on type of age.
https://imgur.com/a/OA6CBpa
with x as (
select ai.invoice_id, ai.invoice_num, ai.invoice_amount, ai.amount_paid,
trial.entity_id, trial.acctd_amount, trial.entered_amount, trial.gl_date,
aps.amount_remaining, aps.gross_amount, aps.due_date, aps.payment_status_flag,
trial.gl_date - aps.due_date dni_opoznienia
from ap_invoices_all ai,
xla.xla_transaction_entities xte,
(
select nvl (tr.applied_to_entity_id, tr.source_entity_id) entity_id,
tr.source_application_id application_id,
sum (nvl (tr.acctd_unrounded_cr, 0)) - sum (nvl (tr.acctd_unrounded_dr, 0)) acctd_amount,
sum (nvl (tr.entered_unrounded_cr, 0)) - sum (nvl (tr.entered_unrounded_dr, 0)) entered_amount,
max(tr.gl_date) gl_date
from xla.xla_trial_balances tr
where 1=1
and tr.definition_code = 'AP_200_1001'
and tr.source_application_id = 200
and tr.gl_date <= fnd_date.canonical_to_date('2019-12-13') -- Data KG
group by nvl (tr.applied_to_entity_id, tr.source_entity_id),
tr.source_application_id
) trial,
ap_payment_schedules_all aps
where 1=1
and ai.invoice_id = 3568325
and nvl(xte.source_id_int_1, -99) = ai.invoice_id
and xte.ledger_id = 1001
and xte.entity_code = 'AP_INVOICES'
and xte.entity_id = trial.entity_id
and xte.application_id = trial.application_id
and ai.invoice_id = aps.invoice_id
)
select x.invoice_id, x.invoice_num, x.entity_id, x.acctd_amount, x.gl_date,
x.amount_remaining, x.gross_amount, x.due_date, x.payment_status_flag,
x.dni_opoznienia, aapl.days_start, aapl.days_to,
case
when x.dni_opoznienia between aapl.days_start and aapl.days_to then x.acctd_amount
else 0
end przedzial
from x,
ap_aging_periods aap,
ap_aging_period_lines aapl
where 1=1
and aap.period_name = 'TEST 5 okresow'
and aap.aging_period_id = aapl.aging_period_id
Based on your comment I guess you need the below
select * from (select x.invoice_id, x.invoice_num, x.entity_id, x.acctd_amount, x.gl_date,
x.amount_remaining, x.gross_amount, x.due_date, x.payment_status_flag,
x.dni_opoznienia, aapl.days_start, aapl.days_to,
case
when x.dni_opoznienia between aapl.days_start and aapl.days_to then x.acctd_amount
else 0
end przedzial
from x,
ap_aging_periods aap,
ap_aging_period_lines aapl
where 1=1
and aap.period_name = 'TEST 5 okresow'
and aap.aging_period_id = aapl.aging_period_id)
where przedzial > 0;

How to calculate median in Hive

I have a hive table,
name age sal
A 45 1222
B 50 4555
c 44 8888
D 78 1222
E 12 7888
F 23 4555
I want to calculate median of age column.
Below is my approach
select min(age) as HMIN,max(age) as HMAX,count(age) as HCount,
IF(count(age)%2=0,'even','Odd') as PCOUNT
from v_act_subjects_bh;
Appreciate any query suggestion
You can use the percentile function to compute the median. Try this:
select percentile(cast(age as BIGINT), 0.5) from table_name
Accepted answer works if you have INT values. If your data contains values between 0-1 such as scores of a model, you may use below formula;
select (percentile(cast(age as BIGINT), 0.5))/100 from table_name
double median = 0;
double term = 0;
double term1 = 0;
if (size % 2 == 1)
{
term = (size + 1 - 1) / 2;
median = term;
}
else if (size % 2 == 0)
{
term1 = (size - 1) / 2;
term1 = term1 + ((size - 1) / 2) + 1;
term1 = term1 / 2;
median = term1;
}
cout << "Median of array: " << median << endl;

Linq - SQL query conversion

Can some one help me to convert this query to linq? I dont know how to use union and then sum in linq.
SELECT Patientname, SUM(A)AS Trec
FROM (SELECT Pm.Patientname, COUNT(*)AS A
FROM Facilitycheckinholdorder Fcho
INNER JOIN Medordertype Mot ON Fcho.Orderseq = Mot.Orderseq
JOIN Patientmaster Pm ON Mot.Patientseq = Pm.Patientseq
AND Fcho.Filleddate BETWEEN '2011-09-01 00:00:00:000' AND '2012-10-16 00:00:00:000'
AND Mot.Facilityid = 139
GROUP BY Pm.Patientname
UNION ALL
SELECT Pm.Patientname, COUNT(*)AS A
FROM Rxqdeliveryholdorder Rdho
INNER JOIN Medordertype Mot ON Rdho.Orderseq = Mot.Orderseq
JOIN Patientmaster Pm ON Mot.Patientseq = Pm.Patientseq
AND Rdho.Filleddate BETWEEN '2011-09-01 00:00:00:000' AND '2012-10-16 00:00:00:000'
AND Mot.Facilityid = 139
GROUP BY Pm.Patientname
) AS Trec
GROUP BY Patientname;
In fact this is not a real question, but I've tried my best...
var lst1 =
from fhco in facilitycheckinholdorder
join mot in meordertype on mot.orderseq equals fhco.orderseq
join pm in patientmaster on mot.patientseq equals pm.patientseq
where
fcho.FilledDate >= new DateTime(2011, 9, 1)
fcho.FilledDate <= new DateTime(2012, 10, 16)
select pm;
var lst2 =
from rdho in rxqdeliveryholdorder
join mot in meordertype on rdho.orderseq equals mot.orderseq
join pm in patientmaster on moit.patientseq equals pm.patientseq
where
fcho.FilledDate >= new DateTime(2011, 9, 1)
fcho.FilledDate <= new DateTime(2012, 10, 16)
select pm;
var res =
from item in lst1.Union(lst2)
select new { Name = item.patientname, Count = lst1.Count() + lst2.Count() };
Key points:
Your outermost query seems redundant.
Your names are not common C# style, and it makes them difficult to read.
UNION ALL corresponds to Concat, not Union.
Getting the Concat out of the way early lets you streamline the query. You could do this in the SQL.
.
var result =
from order in Queryable.Concat(
FacilityCheckInHoldOrder.Select(o => new { o.OrderSeq, o.FilledDate }),
RxqDeliveryHoldOrder .Select(o => new { o.OrderSeq, o.FilledDate }))
where order.FilledDate >= new DateTime(2011, 9, 1) &&
order.FilledDate < new DateTime(2012, 10, 16)
join type in MedOrderType.Where(t => t.FacilityID == 139)
on order.OrderSeq equals type.OrderSeq
join patient in PatientMaster
on type.PatientSeq equals patient.PatientSeq
group by patient.PatientName into grp
select new
{
PatientName = grp.Key,
Trec = grp.Count()
};

How to compare and sum values of multiple periods using LINQ in VB.Net

I have the following example datatable:
Value1 Value2 Customer Product Date
100 50 1000 100 1.8.2010
50 20 1000 101 5.1.2010
200 60 1000 100 6.2.2011
180 100 1001 100 7.3.2010
500 700 1000 100 1.1.2010
300 300 1001 100 4.4.2011
250 600 1000 100 3.3.2011
And now the user should be able to compare multiple periods. In this example the user chose two periods: 1.1.2010 - 31.12.2010 and 1.1.2011 - 31.12.2011. The result of the example should be:
Customer Product SumValue1Period1 SumValue2Period1 SumValue1Period2 SumValue2Period2
1000 100 600 750 450 660
1000 101 50 20 0 0
1001 100 300 100 300 300
How can I do this?
Since you have known number of columns, you can group data by Customer and products and then take conditional sum from grouping and it will make different columns of the resultant query.
Please have a look at following LinqPad program. Sorry, I'm not familiar with VB.Net so I have coded it in C#, but you'll get the fair idea:
void Main()
{
var Period1Start = new DateTime(2010,1,1);
var Period1End = new DateTime(2010,12,31);
var Period2Start = new DateTime(2011,1,1);
var Period2End = new DateTime(2011,12,31);
List<Item> lst = new List<Item>
{
new Item{ Value1 = 100, Value2 = 50, Customer = 1000, Product = 100 , Date = new DateTime(2010,8,1)},
new Item{ Value1 = 50, Value2 = 20, Customer = 1000, Product = 101 , Date = new DateTime(2010,5,1)},
new Item{ Value1 = 200, Value2 = 60, Customer = 1000, Product = 100 , Date = new DateTime(2011,2,6)},
new Item{ Value1 = 180, Value2 = 100, Customer = 1001, Product = 100 , Date = new DateTime(2010,7,3)},
new Item{ Value1 = 500, Value2 = 700, Customer = 1000, Product = 100 , Date = new DateTime(2010,1,1)},
new Item{ Value1 = 300, Value2 = 300, Customer = 1001, Product = 100 , Date = new DateTime(2011,4,4)},
new Item{ Value1 = 250, Value2 = 600, Customer = 1000, Product = 100 , Date = new DateTime(2011,3,3)}
};
var grp = lst.GroupBy(x=>new{x.Customer, x.Product}).
Select(y=> new
{
Customer = y.Key.Customer,
Product = y.Key.Product,
SumValue1Period1 = y.Where(x=>x.Date >= Period1Start && x.Date<= Period1End).Sum(p=>p.Value1),
SumValue2Period1 = y.Where(x=>x.Date >= Period1Start && x.Date<= Period1End).Sum(p=>p.Value2),
SumValue1Period2 = y.Where(x=>x.Date >= Period2Start && x.Date<= Period2End).Sum(p=>p.Value1),
SumValue2Period2 = y.Where(x=>x.Date >= Period2Start && x.Date<= Period2End).Sum(p=>p.Value2)
});
Console.WriteLine(grp);
}
// Define other methods and classes here
public class Item
{
public int Value1{get;set;}
public int Value2{get;set;}
public int Customer{get;set;}
public int Product{get;set;}
public DateTime Date{get;set;}
}
Take a look at
http://msdn.microsoft.com/en-us/vbasic/bb737908
Specifically, the 'GroupBy - Nested' example. It shows using LINQ to group by 'customer's orders, first by year, and then by month.' You situation should be more straight forward since it's just the date range.