Power BI DAX - find repeatability - sql

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.

Related

Cannot cast result from Sub-Select to numeric

I am selecting a list of IDs as a sub-query in a condition but it says it cannot convert '123,456' to numeric. The problem occurs in the last line. DB is Sybase-SQL-Anywhere.
SELECT
ISNULL(SUM(a.menge), 0) AS menge,
ISNULL(SUM(a.wert), 0) AS wert
FROM admin.p_ws_ix_kontrakte_ernte_auswertung_jensek a
WHERE
(a.KtrErnteJahr = ? OR ? IS NULL)
AND (
(a.KtrDispoKennz >= ? OR ? IS NULL)
AND
(a.KtrDispoKennz <= ? OR ? IS NULL)
)
AND a.artikelstammid IN ((SELECT LIST(artikelstammId) FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column))
Remove the LIST():
# replace this:
AND a.artikelstammid IN ((SELECT LIST(artikelstammId) FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column))
# with this:
AND a.artikelstammid IN (SELECT artikelstammId FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column)
Another option would be an exists/correlated subquery:
# replace this:
AND a.artikelstammid IN ((SELECT LIST(artikelstammId) FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column))
# with this:
AND exists (SELECT 1 FROM admin.ws_ix_auswertung_cfg_spalten_artikel b WHERE b.columnId = $column and b.artikelstammId = a.artikelstammid)

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;

Using GROUP BY/CASE with WHEN or IF

note: edited query below.
I am looking to segment a data set according to two criteria:
If a customer has more or less than 4 txns at a specific restaurant
If a customer has more or less than 24 txns at all the other restaurants in that data set.
I am using a conjunction of GROUP BY, CASE and WHEN or IF. I am not sure which approach is best, if either?
SELECT
COUNT(Customer) AS number_of_customers,
AVG (CASE WHEN ItemPrice LIKE '-%' THEN NULL
WHEN ItemPrice LIKE '0%' THEN NULL
ELSE CAST (ItemPrice AS FLOAT) END) AS avg_item_price,
COUNT(DISTINCT(ReceiptIDDesc)) AS number_of_orders,
SUM(CAST(ItemPrice AS FLOAT)) AS total_spend
FROM Tacos
WHERE NOT (PurchaseDate > '01/01/2016 12:00' OR '03/01/2016 12:00'<
PurchaseDate)
GROUP BY
CASE
WHEN (COUNT('MerchantFamily' = %TacoTruck%)> 2) AND COUNT('MerchantFamily' != %TacoTruck%) >24)
THEN 'Fanatic'
WHEN (COUNT('MerchantFamily' = %TacoTruck%)> 2) AND COUNT('MerchantFamily' != %TacoTruck%) <24)
THEN 'Loyalist'
WHEN (COUNT('MerchantFamily' = %TacoTruck%)< 2) AND COUNT('MerchantFamily' != %TacoTruck%) <24)
THEN 'Seldom'
ELSE
'Potential'
END
OR
GROUP BY
CASE
IF(COUNT(IF( 'MerchantFamily' = 'TacoTruck', 1, 0 ) ) > 2, TRUE, FALSE)
AND
IF(COUNT(IF( 'MerchantFamily' != 'TacoTruck',1, 0) ) < 24, TRUE, FALSE), 'Loyalist', NULL )
IF(COUNT(IF( 'MerchantFamily' = 'TacoTruck', 1, 0 ) ) > 2, TRUE, FALSE)
AND
IF(COUNT(IF( 'MerchantFamily' != 'TacoTruck', 1, 0 ) ) > 24, TRUE, FALSE), 'Fanatic', NULL)
IF(COUNT(IF( 'MerchantFamily' = 'TacoTruck', 1, 0 ) ) < 2, TRUE, FALSE)
AND
IF(COUNT( IF( 'MerchantFamily' != 'TacoTruck', 1, 0 ) ) < 24, TRUE, FALSE), 'Seldom', NULL)
ELSE
'Potential'
END
Neither of those approaches will work, you need to group first then consider the aggregated count values through a having clause, or as a nested subquery ("derived table").
A case expression only evaluates values on a per row basis, it does not scan multiple rows.

How can I achieve SQL Pivot statement from LINQ

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();

Using Multiple ANDs and ORs in ANSI SQL

I have a simple SQL query:
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND w.buzz IS NOT NULL
AND w.foo = 12
In pseudo-code, this WHERE clause could be thought of as:
if(specialId == 2394 && buzz != null && foo == 12)
I now want to change this query so that it returns all widgets whose special_id is 2394, and whose buzz is not null, and whose foo is 12, OR whose special_id is 2394, and whose blah is 'YES', and whose num is 4. In pseudo-code:
if(specialId == 2394 && (buzz != null && foo == 12) || (blah == "YES" && num == 4))
I tried the following, only to get errors:
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND
(
w.buzz IS NOT NULL
AND w.foo = 12
)
OR
(
w.blah = 'YES'
AND w.num = 4
)
Any ideas? Thanks in advance!
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND
(
(
w.buzz != null
AND w.foo = 12
)
OR
(
w.blah = 'YES'
AND w.num = 4
)
)
Add additional brackets surrounding "OR", because "OR" has less priority than "AND".