RunningSum inside another - sap

I have a report with the following data
IdSource 20170629 20170628 20170626 20170625 20170624 20170623
Id1. OK KO N/A KO OK KO
I want to count the number of days my data (status of a workflow) is KO. N/A means the worflow is not expected, so it should not be counted.
Expected results :
IdSource 20170629 20170628 20170626 20170625 20170624 20170623
Id1. OK KO(2) N/A KO(1) OK KO(1)
The count must be reset at each OK.
In SQL, I would do
select t.*,
sum(case when status = 'KO' then 1 else 0 end) over (partition by id, cume_ko order by date) as nbDayKO
from (select t.*,
sum(case when status = 'OK' then 1 else 0 end) over (partition by id order by date) as cume_ko
from t
) t
I tried to use the RunningSum function without success:
I need to inverse the sort on the date
I cannot use the result of a runningSum inside another.
Thanks for your help

It's ugly and not very efficient, but I did not find any other solutions. Here is how I did it :
If ([status] = 0) Then 0
Else (
(If (RelativeValue([status];([dayOfWeek]);1) = 1) Then
If (RelativeValue([status];([dayOfWeek]);2) = 1) Then
If (RelativeValue([status];([dayOfWeek]);3) = 1) Then
If (RelativeValue([status];([dayOfWeek]);4) = 1) Then
If (RelativeValue([status];([dayOfWeek]);5) = 1) Then
If (RelativeValue([status];([dayOfWeek]);6) = 1) Then
If (RelativeValue([status];([dayOfWeek]);7) = 1) Then
If (RelativeValue([status];([dayOfWeek]);8) = 1) Then
If (RelativeValue([status];([dayOfWeek]);9) = 1) Then
If (RelativeValue([status];([dayOfWeek]);10) = 1) Then
If (RelativeValue([status];([dayOfWeek]);11) = 1) Then
If (RelativeValue([status];([dayOfWeek]);12) = 1) Then
If (RelativeValue([status];([dayOfWeek]);13) = 1) Then
If (RelativeValue([status];([dayOfWeek]);14) = 1) Then
If (RelativeValue([status];([dayOfWeek]);15) = 1) Then 15
Else 14
Else 13
Else 12
Else 11
Else 10
Else 9
Else 8
Else 7
Else 6
Else 5
Else 4
Else 3
Else 2
Else 1
Else 0)+[status])

Related

SQL - JOIN with condition CASE - how to make - if condition is met stop to meet next one

Cashier can input to field C40_DATA 3 different values (9962**********, id_invoice, web_order)
what I would like to have as result:
if substr from C40_DATA contains p.id_invoice => show these lines
if C40_contains contains id_web_order or id_incvoice => show these lines
-> it means point 1 shows always but point 2 -> do not show both, if exist id_web_order, show it and stop, if it not exists find id_incvoice
When I create this (below), result contains all 3 together, but I need 1 + (if exist 2 and if not find 3)
select * from web_data p
inner join POS_DATA re on
(case
when substr(re.C40_DATA,5,8) = p.id_invoice and substr(re.C40_DATA,1,4) ='9962' then 1 else
(case
when re.C40_DATA = p.id_web_order and p.d_mnozstvi < '0' then 1 else
(case
when re.C40_DATA = p.id_invoice and p.d_mnozstvi < '0' then 1 else 0 END)
END)
END=1)
Could you please help how to make contitions in JOINs which do - if one condition is met stop and do not find the next one?
Thank you,
Your attempted query would have been better written this way:
select * from web_data p
inner join POS_DATA re on
substr(re.C40_DATA, 5, 8) = p.id_invoice and substr(re.C40_DATA, 1, 4) = '9962'
or re.C40_DATA = p.id_web_order and p.d_mnozstvi < '0'
or re.C40_DATA = p.id_invoice and p.d_mnozstvi < '0'
Had you really needed to do this as a case expression it could have been done as below. The cases fall through in order:
case
when substr(re.C40_DATA, 5, 8) = p.id_invoice and substr(re.C40_DATA, 1, 4) ='9962' then 1
when re.C40_DATA = p.id_web_order and p.d_mnozstvi < '0' then 1
when re.C40_DATA = p.id_invoice and p.d_mnozstvi < '0' then 1
end = 1
As far as matching only on a single condition, I think you want something like this:
with data as (
select *,
case
when re.C40_DATA = '9962' + p.id_invoice then 1
when re.C40_DATA = p.id_web_order and p.d_mnozstvi < '0' then 2
when re.C40_DATA = p.id_invoice and p.d_mnozstvi < '0' then 3
end as match_rank,
min(case
when re.C40_DATA = '9962' + p.id_invoice then 1
when re.C40_DATA = p.id_web_order and p.d_mnozstvi < '0' then 2
when re.C40_DATA = p.id_invoice and p.d_mnozstvi < '0' then 3
) over (partition by p.id_invoice, p.web_order) as min_match_rank
from web_data p
inner join POS_DATA re on
re.C40_DATA = '9962' + p.id_invoice
or re.C40_DATA = (p.id_web_order, p.id_invoice) and p.d_mnozstvi < '0'
)
select * from data where match_rank = min_match_rank;
I've taken the liberty of rewriting some of your conditions in case those options are useful to you. Also, I'm not sure what < '0' is supposed to mean. Finally, I'm not sure which values to be partitioning over because I don't understand the relationship between id_invoice and id_web_order.

CASE WHEN THEN Cannot perform an aggregate function on an expression containing an aggregate or a subquery

this is my code:
SELECT SUM
(CASE
WHEN (dbo.EMBARQUE.EmbEst) = 0 THEN
0
WHEN (dbo.EMBARQUE.EmbEst) = 3 THEN
0
WHEN (dbo.EMBARQUE.EmbEst) = 6 THEN
0
WHEN (dbo.EMBARQUE.EmbEst) = 7 THEN
CASE
WHEN (SELECT COUNT (dbo.CUMPLIDO.CumpCod) from dbo.CUMPLIDO where dbo.CUMPLIDO.EmbCod = dbo.EMBARQUE.EmbCod and dbo.CUMPLIDO.CumpVol = 0) > 0 THEN
0
ELSE
dbo.EMBARQUE.EmbVol
END
ELSE
dbo.EMBARQUE.EmbVol
END) FROM dbo.EMBARQUE
You have a subquery inside sum(). That isn't allowed. This version uses a subquery to calculate the flag you want and then moves the filtering logic to the WHERE clause:
SELECT SUM(e.EmbVol)
FROM (SELECT e.*,
(CASE WHEN EXISTS (SELECT 1 FROM dbo.CUMPLIDO c WHERE c.EmbCod = e.EmbCod AND c.CumpVol = 0)
THEN 1 ELSE 0
END) as is_CumpVol_0
FROM dbo.EMBARQUE e
WHERE e.EmbEst NOT IN (0, 3, 6)
) e
WHERE e.EmbEst <> 7 OR is_CumpVol_0 = 0;

Combining Case Statements in a View

I have these two case statements and can not for the life of me figure out how to combine them to show in a MSSQL view. Any help would be great.
CASE WHEN [ordertype] = '2' THEN [CommissionAmt1] * - 1 ELSE [CommissionAmt1] END
and
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN 0 ELSE CommissionAmt1 END
Just adding the first case to wherever the CommissionAmt1 is referenced in the second statement.
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CASE WHEN [ordertype] = '2' THEN
[CommissionAmt1] * - 1
ELSE
[CommissionAmt1]
END
END
Or going the other way. It was hard to understand which way the calculation needs to be performed. The only hint was []
CASE WHEN [ordertype] = '2' THEN
(
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CommissionAmt1
END
) * - 1
ELSE
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CommissionAmt1
END
END
Either way, you would be able to save some calculations by sub querying the dependent value.
SELECT
*,
ValueWithDependant=CASE WHEN (Dependant>0) THEN (SomeValue / Dependant) ELSE NULL END
FROM
(
SELECT
X,Y,Z,
Dependant=CASE WHEN SomeValue=1 THEN 1 ELSE 0 END
FROM
SomeTable
)AS DETAIL

Understanding case expression in the "Where" clause

I've got this code here and you can see from my Pseudocode what I'm trying to accomplish
select *
from dbo.BenefitsForms
inner join Dependents on BenefitsForms.UserId = Dependents.BenefitsForm_UserId
inner join CoverageLevels on BenefitsForms.MedicalId = CoverageLevels.Id
where (BenefitsForms.MedicalId > 0 AND BenefitsForms.MedicalId < 13)
AND Dependents.IsSpouse = CASE when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0 end
when CoverageLevels.[Level] = 4 then [any, it doesnt matter] <--- my desire but it doesn't work.
What can I do to get the effect I desire in the brackets? If Coverage Level = 4 then I don't care what Dependents.IsSpouse is, I don't even need to sort by it anymore.
Assuming that isSpouse can only be 0 or 1... if CoverageLevels.Level is 4, then compare isSpouse to itself, which will always result in true:
AND Dependents.IsSpouse = CASE
when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0
when CoverageLevels.[Level] = 4 then Dependents.IsSpouse
END
Alternately, this can also be expressed without the CASE:
WHERE
BenefitsForms.MedicalId > 0
AND BenefitsForms.MedicalId < 13
AND (
(Dependents.IsSpouse = 1 AND CoverageLevels.[Level] = 2)
OR (Dependents.IsSpouse = 0 AND CoverageLevels.[Level] = 3)
OR CoverageLevels.[Level] = 4
)

SQL Counting Records with Count and Having

I'm having problems with what I thought was a simple query to count records:
SELECT req_ownerid, count(req_status_lender) AS total6
FROM bor_requests
WHERE (req_status_lender = 0 AND req_status_borrower = 0) OR
(req_status_lender = 1 AND req_status_borrower = 1)
GROUP BY req_ownerid
HAVING req_ownerid = 70
I thought this would count all the records where (req_status_lender = 0 AND req_status_borrower = 0) and (req_status_lender = 1 AND req_status_borrower = 1) and then give me the total but it only gives me the total for either (req_status_lender = 0 AND req_status_borrower = 0) or (req_status_lender = 1 AND req_status_borrower = 1).
Any ideas what I'm doing wrong?
You should use the HAVING clause only to limit on something that's been aggregated in your query above - e.g. if you want to select all those rows where a SUM(....) or COUNT(...) is larger than say 5, then you'd use HAVING SUM(...) > 5
What you're doing here is a standard WHERE clause - add it there!
SELECT req_ownerid, count(req_status_lender) AS total6
FROM bor_requests
WHERE req_ownerid = 70
AND ((req_status_lender = 0 AND req_status_borrower = 0) OR
(req_status_lender = 1 AND req_status_borrower = 1))
GROUP BY req_ownerid