Case statement with division - sql

I have case statement below as
count(CASE WHEN time_lag / 10000 >= 0 AND time_lag / 1000 <= 50 THEN 1 END) AS [0 - 50]
but am getting error on syntax error, is there proper way to divide in case statement? thanks

You need to add quotes to the desired column name (if it's not going to follow traditional naming rules.
Change:
select count(...) AS [0 - 50]
To:
select count(...) AS "[0 - 50]"
Btw, the exact syntax error you got was Syntax error: unexpected '['. (line 7). Please make sure to include the exact error you get in future posts.

Idenfitifers containing special characters have to be quoted with ". The query could be further simplified by using COUNT_IF:
select count_if(time_lag / 10000 >= 0 AND time_lag / 1000 <= 50) AS "[0 - 50]"
=>
select count_if(time_lag/1000 BETWEEN 0 AND 50) AS "[0 - 50]"
=>
-- no epxression on the column
select count_if(time_lag BETWEEN 0 AND 50*1000) AS "[0 - 50]"

Related

SQL "expected DATE got NUMBER"

When running the below script I get the error "ORA-00932: inconsistent datatypes: expected DATE got NUMBER". Doesn't give me a line on which the error is at. Using Oracle DB.
with reg_det as (
SELECT MCI.MEASR_COMP_ID
FROM D1_MEASR_COMP_IDENTIFIER MCI, D1_MEASR_COMP_IDENTIFIER MCR, D1_MEASR_COMP MC, D1_DVC_CFG DC, D1_DVC_IDENTIFIER DVI
WHERE MCI.MC_ID_TYPE_FLG = 'D1EI'
AND MCI.MEASR_COMP_ID = MC.MEASR_COMP_ID
AND REGEXP_SUBSTR(MCI.ID_VALUE, '[^-]+', 1, 13) = 'INT'
AND MCR.MC_ID_TYPE_FLG = 'CMRN'
AND MCR.ID_VALUE = :REG
AND MCR.MEASR_COMP_ID = MC.MEASR_COMP_ID
AND MC.DEVICE_CONFIG_ID = DC.DEVICE_CONFIG_ID
AND DVI.D1_DEVICE_ID = DC.D1_DEVICE_ID
AND DVI.DVC_ID_TYPE_FLG = 'D1SN'
AND DVI.ID_VALUE = :MTR),
gap_dates as (select to_char((:SDTTM + level -1),'YYYY-MM-DD') as read_date, 0 as interval_count, 'M' as quality, 0 as daily_load
from dual
connect by level <= (:EDTTM - :SDTTM) )
,read_data as (SELECT to_char(trunc(MSRMT_DTTM - 1/1440),'YYYY-MM-DD') as read_date,
count(1) as interval_count,
case
when min(msrmt_cond_flg) > 500000 THEN 'A'
when min(msrmt_cond_flg) > 400000 and min(msrmt_cond_flg) <= 500000 then 'F'
when min(msrmt_cond_flg) > 300000 and min(msrmt_cond_flg) <= 400000 then 'S'
when min(msrmt_cond_flg) > 200000 and min(msrmt_cond_flg) <= 300000 then 'E'
when min(msrmt_cond_flg) <= 200000 then 'M' end as quality,
sum(msrmt_val) as daily_load FROM REG_DET REG, D1_MSRMT DATA
WHERE DATA.MEASR_COMP_ID = REG.MEASR_COMP_ID
AND MSRMT_DTTM > :SDTTM
AND MSRMT_DTTM <= (:EDTTM + 1)
GROUP BY trunc(MSRMT_DTTM - 1/1440))
select * from read_data
union
select * from gap_dates a where 1=1 and not exists (select 1 from read_data b where a.read_date = b.read_date);
A lot of the code provided is impossible to check as we don't know the structure of your tables nor the datatypes of the columns. I tried to cut the code in pieces to do the tests, and the only part that is returning ORA-00932 error is in the WHERE clause of the read_data cte.
I'm not sure if that is your problem, but if it is it will not be the only one. What I wanted to say is that even if you correct this one there will be more errors. Let me explain - the reported error could be simulated if you bind a character value to your :EDTTM variable. Other errors would pop up if :SDTTM is of type character.
Here is the test using construction from the mentioned WHERE clause:
WHERE
DATA.MEASR_COMP_ID = reg.MEASR_COMP_ID
AND MSRMT_DTTM > :SDTTM
AND MSRMT_DTTM <= (:EDTTM + 1)
The last condition tested on DUAL table (assuming that MSRMT_DTTM is of type DATE) compares DATE to CHARACTER + NUMBER like in this SQL
SELECT 'anything' FROM DUAL WHERE SYSDATE <= '24-SEP-22' + 1
This results with:
/*
SQL Error: ORA-00932: inconsistent datatypes: expected DATE got NUMBER
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*/
If any or both of your %DTTM variables are of type character then there will be more errors (not ORA-00932) throughout your code. Additionaly, you should really consider the advice form comments to use ANSI SQL join syntax. Regards...

Percentage of two values returning NULL

Same as yesterdays question which has been answered successfully but different problem. I have two values, 1 and 0 for which I need to calculate the percent change. Based on this website http://www.percent-change.com/index.php?y1=1&y2=0 the percent change between 1 and 0 is -100%. Based on the suggested formula which is (((y2- y1))/ y1) my code looks like this.
DefinedYearVSPriorYearIndividual = ((( CTEDefinedYear.IndividualCases - CTEPreviousYear.IndividualCasesLastYear ))
/ ( CTEPreviousYear.IndividualCasesLastYear ) ) * 100
which returns NULL.
The two numbers are
CTEDefinedYear.IndividualCases = 1
CTEPreviousYear.IndividualCasesLastYear = 0
The desired result should be -100%.
Can anybody see what I'm doing wrong?
Here is the answer.
Declare #y1 as int =1;
Declare #y2 as int =0;
select (((#y2- #y1))/ #y1)*100
Output is -100. You missed the *100 part.
In your case, You switched variables. attached formula is right one.
select ((0 - 1) / 1)*100;
But you used select ((1 - 0) / 0)*100;
so, you will get an error:
Msg 8134, Level 16, State 1, Line 1
Divide by zero error encountered.
You have to handle 0 in the division side, with CASE logic, to avoid divide by zero error.
DECLARE #CTEDefinedYear_IndividualCases INT = 1
DECLARE #CTEPreviousYear_IndividualCasesLastYear INT = 0
SELECT ((#CTEDefinedYear_IndividualCases - #CTEPreviousYear_IndividualCasesLastYear) / (CASE WHEN #CTEPreviousYear_IndividualCasesLastYear = 0 THEN 1 ELSE #CTEPreviousYear_IndividualCasesLastYear END)) * 100
Got it to work with this code.
DefinedYearVSPriorYearIndividual = ISNULL(100.0 *
(ISNULL(CTEDefinedYear.IndividualCases,0)
- ISNULL(CTEPreviousYear.IndividualCasesLastYear,0))
/ NULLIF(CTEPreviousYear.IndividualCasesLastYear,0),0)

Divide by zero error in SQL even though I excluded the zero cases?

Here is the code that I've been trying to run:
SELECT C.* FROM
(SELECT
B.[OUTSIDE_ROW],
B.[INSIDE_ROW],
B.[r_HU_vac_ns],
B.[r_HU_vac_ns_MOE],
CASE WHEN B.[r_HU_vac_ns] = 0 THEN 999 ELSE B.[r_HU_vac_ns_MOE]/B.[r_HU_vac_ns] END AS [PCT]
FROM
(SELECT
A.[OUTSIDE_ROW],
A.[INSIDE_ROW],
(A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT] AS [r_HU_vac_ns],
(1/A.[HU_VACANT]) * POWER(
CASE WHEN ((A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT]) * POWER(A.[HU_VACANT_MOE], 2) < POWER(A.[HU_VACANT_MOE], 2) + POWER(A.[HU_VACANT_SEASONAL_RECREATIONAL_MOE], 2) THEN POWER(A.[HU_VACANT_MOE], 2) + POWER(A.[HU_VACANT_SEASONAL_RECREATIONAL_MOE], 2) - (((A.[HU_VACANT] - A. [HU_vACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT]) * POWER(A.[HU_VACANT_MOE], 2))
ELSE POWER(A.[HU_VACANT_MOE], 2) + POWER(A. [HU_VACANT_SEASONAL_RECREATIONAL_MOE], 2) + (((A.[HU_VACANT] - A. [HU_vACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT]) * POWER(A.[HU_VACANT_MOE], 2)) END, 0.5) AS [r_HU_vac_ns_MOE]
FROM
(SELECT
[OUTSIDE_ROW],
[INSIDE_ROW],
SUM([ESTIMATE_1]) AS [HU_VACANT],
POWER(SUM(POWER([MOE_1], 2)), 0.5) AS [HU_VACANT_MOE],
SUM([ESTIMATE_2]) AS [HU_VACANT_SEASONAL_RECREATIONAL],
POWER(SUM(POWER([MOE_2], 2)), 0.5) AS [HU_VACANT_SEASONAL_RECREATIONAL_MOE]
FROM #TEST_TABLE
GROUP BY [OUTSIDE_ROW], [INSIDE_ROW]) A
WHERE A.[HU_VACANT] > 0) B ) C
WHERE C.[PCT] < 0.2
Every time I run it, I get the following error:
Msg 8134, Level 16, State 1, Line 533
Divide by zero error encountered.
However, if I take off the last line of code (the following WHERE clause) the code runs fine:
WHERE C.[PCT] < 0.2
Just from looking at my query, can anyone tell me what I'm doing wrong? I thought I eliminated all PCT values that were zero with the CASE WHEN statement below so this error is baffling me:
CASE WHEN B.[r_HU_vac_ns] = 0 THEN 999 ELSE B.[r_HU_vac_ns_MOE]/B.[r_HU_vac_ns] END AS [PCT]
If it helps, PCT is cast as floating point.
Thanks.
SQL Server reserves the right to rearrange calculations. That means that the calculation in a SELECT can happen before filtering occurs. This is true even when the filters are in subqueries and CTEs.
The only way to guarantee order of calculation is CASE. However, I think it is easier to just use NULLIF(), an ANSI standard function. Instead of logic like this:
(A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT] AS [r_HU_vac_ns],
do:
(A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/NULLIF(A.[HU_VACANT], 0) AS [r_HU_vac_ns],
Instead of filtering out the records using
WHERE A.[HU_VACANT] > 0
You should filter out the records at root level
having SUM([ESTIMATE_1]) > 0
You could also use nullif function but that will result producing NULL where you have zero

Postgres syntax error in if condition

I am trying to calculate commission and according to that commission value (commiss) i want to update a column value fixed_fee
select st1.* ,(st1.order_item_value * st1.commission_rate)/100 commiss ,
if commiss < 50 then
update payment_error set fixed_fee = -5 where commiss <= 50
else if commiss >= 50 then
update payment_error set fixed_fee = -10 where commiss >=50
else
end if
from payment_error as st1 join payment_error as st2 on st1.order_item_id=st2.order_item_id ;
while running is then error come is :
ERROR: syntax error at or near "<"
LINE 2: if commiss<50 then
^
********** Error **********
ERROR: syntax error at or near "<"
SQL state: 42601
Character: 87
You can't use if in SQL. This is only available in procedural languages like PL/pgSQL.
But more importantly you cannot embed an update statement inside a select statement like that.
What you are trying to do can be done with a single UPDATE statement using a CASE:
update payment_error
set fixed_fee = case
when (order_item_value * commission_rate)/100 <= 50 then -5
else 5 --<<< different value here
end;
You are setting the fixed_fee to -5 in both cases - I assume that is a typo, and you do mean to assign a different fee for the case when the comission is greater than 50
You cannot use update and select together. To update you can try this:
update payment_error
set fixed_fee = case when (order_item_value * commission_rate * .01) < 50 then -5
else 5 --In your case you have use both as -5 so change it as per your reqm

Can we execute select statement in AND conditon (getting error missing expression)

I am building a complex query. First here is my query
select LOSA_APP.app_ref_no AS "App.Ref.No."
from losa_app LOSA_APP,
losa_app_z LOSA_APP_Z
where
LOSA_APP.app_status='A'
and
trunc(sysdate) between (nvl(LOSA_APP_Z.li_dt, LOSA_APP_Z.li_collect_dt)) AND ((trunc(sysdate)))
and
(trunc(sysdate) - nvl(losa_app_z.li_dt,losa_app_z.li_collect_dt)) > 90
and
(select losa_app_z.app_ref_no
from losa_app_z
where (trunc(sysdate) - nvl(losa_app_z.li_dt, losa_app_z.li_collect_dt)) > 90
)
The problem is if i run the last query separately or i omit the last query then it is run fine, like if i only run
(select losa_app_z.app_ref_no
from losa_app_z
where (trunc(sysdate) - nvl(losa_app_z.li_dt, losa_app_z.li_collect_dt)) > 90)
but if i run the whole query then i get the error
ORA-00936: missing expression
00936. 00000 - "missing expression"
*Cause:
*Action:
Error at Line: 7 Column: 128
Line 7 is the line at which my last query and
(select losa_app_z.app_ref_no from losa_app_z.... is present. What i am doing wrong ? Please help.
Thanks
You should compare result of this query
and
(select losa_app_z.app_ref_no
from losa_app_z
where (trunc(sysdate) - nvl(losa_app_z.li_dt, losa_app_z.li_collect_dt)) > 90
) = something_here
to something.
For future always try to manage your brackets properly. Count them if necessary.