SQL returns wrong value (?) - sql

SQL Case statement with formula returns the wrong value in the column. What I am trying to do is to calculate the absolute value based on several conditions. First of all when the risk_class is either "Not enough samples" or "Regular price" the absolute value should be zero. Secondly, when the difference between the mode and the price is less than zero, the absolute value should be zero. If all these conditions are not met, then the risk_abs should be the difference between the mode and price multiplied by the quantity column corresponding with the row.
UPDATE dbo.import_company
SET risk_abs = ROUND(t.risk_abs, 0)
FROM (
SELECT invoice_ref, risk_class, modus, price, quantity,
CASE
WHEN risk_class = 'Onvoldoende observaties' THEN 0
WHEN risk_class = 'Gefactureerd tegen reguliere prijs' THEN 0
WHEN (modus - price) < 0 THEN 0
ELSE (modus - price) * quantity
END AS risk_abs
FROM dbo.import_company
)
t WHERE t.invoice_ref = dbo.import_company.invoice_ref
SELECT invoice_ref, article_code, quantity, price, modus, risk_class, risk_abs
FROM dbo.import_company
WHERE risk_class = 'Gefactureerd tegen reguliere prijs'
I don't understand why me result is different, and the formulas don't work. See below
I don't get how the 140 is calculated and why it ignores all statements?
Any advice and tips on what I am doing wrong are welcome!

There's no aggregation here or any other reason I can see to use a subquery to do the CASE logic. So we can get rid of that and the too-loose attempt at correlation between the subquery and the table:
UPDATE dbo.import_company
SET risk_abs = ROUND(CASE
WHEN risk_class = 'Onvoldoende observaties' THEN 0
WHEN risk_class = 'Gefactureerd tegen reguliere prijs' THEN 0
WHEN (modus - price) < 0 THEN 0
ELSE (modus - price) * quantity
END, 0)

Related

PowerBI Get Previous row value according to filters

I have a table with different objects and the objects evolve over time. One object is identified by object_number and we can track it with the object_line_number. And every evolution of the object has a status.
I want to calculate the time elapsed between some status.
Below is my table for one object_number "us1":
In yellow are the rowscontaining the starting date. They are found if (status_id = 0 and (old_status <> 0 or object_line_number = 1) and emergency_level = 1).
In green are the rows containing the ending date. They are found if (status_id =2,3,4,5 and old_status = 0).
The column old_status does not exist in the table. This is the status of the previous row (according to the object)line_number). I am retrieving it thanks to the following measure:
old_status = CALCULATE (
MAX(fact_object[status_id]),
FILTER (
ALL(fact_object),
fact_object[object_line_number] = IF(fact_object[object_line_number]=1, fact_object[object_line_number], MAX (fact_object[object_line_number])-1)),
VALUES (fact_object[object_number]))
I am in DirectQuery mode, so a lot of functions are not present for Calculated Columns, that's why I am using Measures.
Once that is done, I want then to be able to get for every green row the date_modification of the previous yellow row.
In this example, the result would be 4/4 then 1. So that I can calculate the time difference between the date_modification of the current green row and the date_modification of the previous yellow row.
So I was thinking of adding a new column named date_received, which is the date_modification of the previous yellow row;
From there, I just have to keep only the green rows and calculate the difference between date_modification and date_received.
My final calcul is actually to have this :
Result = (number of green rows which date difference between date_modification and date_received <= 15 min) / (number of green rows
which DAY(date_modification) = DAY(date_received))
But I don't know how to do it.
I have tried in the same spirit of the old_status measure to do this:
date_received = CALCULATE (
MAX(fact_object[date_modification]),
FILTER (
ALL(fact_object),
(fact_object[object_line_number] = MAX (fact_object[object_line_number])-1) && MY OTHER FILTERS
),
VALUES (fact_object[object_number])
)
But didn't succeed.
In SQL, the equivalent would be like this:
SELECT
SUM(CASE WHEN (DATEDIFF(MINUTE, T.date_received, T.date_planification) <= 15) THEN 1 ELSE 0 END) /
SUM(CASE WHEN (DAY(T.date_received) = DAY(T.date_planification)) THEN 1 ELSE 0 END) as result
FROM (
SELECT *, T.status_id as current_status,
LAG(T.date_modification) OVER(PARTITION BY T.object_number ORDER BY T.object_line_number) as date_received,
T.date_modification as date_planification
FROM
(
select *,
LAG (status_id) OVER(PARTITION BY object_number ORDER BY object_line_number) AS old_status
from dbo.fact_object
) AS T
WHERE ((T.status_id = 0 AND (T.old_status <> 0 OR T.object_line_number = 1) AND T.emergency_level = 1) OR (T.old_status = 0 AND T.status_id IN (2,3,4,5)))--974
) AS T
WHERE old_status = 0
(Well maybe there is a better way to do it in SQL that I've done).
How can I achieve this?
In this case, I would first sort the table by Object then by Object Line number (or Date Modified - but these appear not to change for each row.)
Duplicate the table
Table1 - Add an index starting at 1
Table2 - Add an index starting at 0
From Table1, merge it with table2, using the new index fields
Expand the MergedStatus ID (rename to NextStatusID) and the Object (rename to NextObject) field.
You can now create a new conditional column to compare the two status fields. E.g. Status 2 = If Object = NextObject then [NextStatusID] else null

How to using subquery values in arithmetic operations

My manager wants to see what is total values of our suppliers shipments, and what is the total values of their invoices recorded. So he can see the differencies and want from suppliers to unsended invoices.
Here is my code.
It is working on accounting table and shipment detail table.
fis_meblag0 is always little from zero because it is 320 account so I mutiply it -1 for get real value.
sth_tutar is value of shipment, sth_vergi is VAT and so the sum of them is equal to sum of total with VAT.
Now the hard part.
Manager wants to diference between them in a other column and also sort the valuez z to a.
I know I can reuse same subselect for the getting totals but I want to know that can I achieve this without using the same subquery again.
I mean in first subselect I have the total, in last column I only need just the total, can I use total without compute it again?
Regards
select
ch.cari_kod as Carikod,
ch.cari_unvan1 as Unvani,
(select (sum(mf.fis_meblag0) * -1)
from dbo.MUHASEBE_FISLERI mf
where (mf.fis_tarih > '20141231' and mf.fis_tarih < '20150201')
and mf.fis_hesap_kod = ch.cari_kod
and mf.fis_meblag0 < 0) as mtoplam,
(Select sum (sth.sth_tutar + sth.sth_vergi)
from dbo.STOK_HAREKETLERI sth
where (sth.sth_tarih > '20141231' and sth.sth_tarih < '20150201')
and sth.sth_cari_kodu = ch.cari_kod
and sth.sth_normal_iade = 0
and sth.sth_tip = 0) as stoplam
from
dbo.CARI_HESAPLAR ch
where
ch.cari_kod like '320%'
try this query:
select Carikod, Unvani, mtoplam, stoplam, mtoplam - stoplam as Grand_total
from
(
-- your full query here
) T

conditional select between multiple fields

I have a table with a certain flag called FL_virtual, if this flag equals 1 i need to get my stock in a special way using a function
now i want to make a select statement with it but depending on this flag i need to adjust my select to use a certain function instead of a subquery
so presume i start with this select statement
select product_name,..(other options from the product table),
(select sum(qy_stock) from STOCK where warehouse_id = 1) as 'qy_stock_internal',
(select sum(qy_stock) from STOCK where warehouse_id = 2) as qy_stock_external
From product
now i need to change the subquery (qy_stock) with a call to a function when the fl_virtual flag is 1
so that it becomes like this
select product_name,..(other options from the product table),
FN_GET_stock_PRODUCT(1) as qy_stock_internal,
FN_GET_stock_PRODUCT(2) as qy_stock_external
from product
so i thought a simple if then else structure will do but for some reason i can't get it to work
this is how i thought it would look
select product_name,..(other options from the product table),
IF fl_virtual > 0 THEN
(select sum(qy_stock) from STOCK where warehouse_id = 1) as 'qy_stock_internal',
(select sum(qy_stock) from STOCK where warehouse_id = 2) as qy_stock_external
ELSE
FN_GET_stock_PRODUCT(1) as qy_stock_internal,
FN_GET_stock_PRODUCT(2) as qy_stock_external
END IF
but it doesn't work , anyone got an idea?
You're close - just use CASE instead of IF (you have to repeat your condition, since you cannot easily return two columns from a single CASE (see P.S.):
select product_name,
..(other options from the product table),
(CASE
WHEN fl_virtual > 0 THEN
(select sum(qy_stock) from STOCK where warehouse_id = 1)
ELSE
FN_GET_stock_PRODUCT(1)
END) as qy_stock_internal,
(CASE
WHEN fl_virtual > 0 THEN
(select sum(qy_stock) from STOCK where warehouse_id = 2)
ELSE
FN_GET_stock_PRODUCT(2)
END) as qy_stock_external
P.S.: It is possible to return multiple values from a single CASE, e.g. using Object Types, but that's stuff for a different question :-)
Best way is to use a union select with those 2 different queries and contitions.
Btw. the names stock and warehouse look like a typical school work examin.

How do I use a calculated column within a Scalar function in a CTE in a Stored procedure..

Ok, the title is probably confusing.
I need to use a case statement to calculate the amount of tax to deduct offa value.
This reduced value will be used in a Scalar function to calculate another value in a CTE in a Stored procedure..
How can I re-use this calculated column inside the scalar function?? I have tried the following.
paidminusIPT = case when country = "ireland" then (paid - 1) else paid end,
dbo.fnEarnedPrem(a,b,c,d,paidminusipt,e,f)
please note, this isn't the exact code, just a quick reference..
Is this possible to do?
Regards.
You should use full expression instead of just column name:
paidminusIPT = case when country = "ireland" then (paid - 1) else paid end,
dbo.fnEarnedPrem(a,b,c,d,case when country = "ireland" then (paid - 1) else paid end,e,f)
or use CTE
;WITH C as(
SELECT a,b,c,d,e,f,paidminusIPT = case when country = "ireland" then (paid - 1) else paid end FROM SomeTable)
Select *,dbo.fnEarnedPrem(a,b,c,d,paidminusipt,e,f) FROM C

Linq Query Handling Null Values

From r In ReceiptLines
Where
r.RECEIPT.RECEIPTDATE >= _reportStartDate
And r.RECEIPT.RECEIPTDATE <= _reportEndDate
Let amount = r.QUANTITY * r.PRICE
Let discount = r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT)
where discount > 0
Group By Department = r.ITEMSTYLE.ITEM.CATEGORY.DEPARTMENT.DEPARTMENTNAME
Into Sales = Sum(amount - discount),
Average = Average(amount - discount),
Count = Count()
I am fetching all departments and their sales, average, count from the ReceiptLine, Receipt, ReceiptDiscount tables. The problem i am facing is, if i remove where discount > 0, I am getting null exception. But if I include that, then I only get sales that has discount.
How would I write query that bring all sales less discount (if it has one). Any help is highly appreciated.
This is a common pitfall with LINQ2SQL.
The function SUM in SQL returns null if there are no items in the collection, but the signature of Enumerable.Sum() returns an int. This gives a runtime exception when the SQL query return null where the LINQ2SQL provider expects an integer.
The solution is to cast the result of the sum to a nullable integer and use GetValueOrDefault to convert the null-case to 0.
Replace
Let discount = r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT)
with
Let discount = CType(r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT), Integer?).GetValueOrDefault(0)
Have you tried:
...
Let amount = r.QUANTITY * r.PRICE
Let nDiscount = r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT)
Let discount = IIf(nDiscount == Nothing, 0, nDiscount)
Group By Department = r.ITEMSTYLE.ITEM.CATEGORY.DEPARTMENT.DEPARTMENTNAME
...