Decode function in oracle for null values - sql

I am working on a java code in which i am comparing the user input values with database values.
I am writing the code to display the alert message to the users on selection of particular division from drop down menu. But there are some alert message which I want to display to all users of every division.
I have the table columns as sr_n0, alert_desc, div_code, alert_flag.
Initially I am checking the div_code = 'division code' and alert_flag = 'y' to display division specific alert message.
But now I want to know how the decode function will work if div_code = null and alert_flag = 'y'.
I have tried this SQL query :
SELECT DECODE(DIV_CODE,'61','Division A',
'62','Division B',
'ALL')
FROM ALERTS WHERE ALERT_FLAG='Y';

If there is no match, then the result will be 'ALL'. I would strongly encourage you to use the ANSI-standard CASE statement, instead of the Oracle-specific DECODE() function:
SELECT (CASE DIV_CODE
WHEN '61' THEN 'Division A'
WHEN '62' THEN 'Division B'
ELSE 'ALL'
END)
FROM ALERTS
WHERE ALERT_FLAG = 'Y';

I solved this issue by writing simple SQL command and it worked for me.
SELECT ALERT_DESC FROM ALERTS A
WHERE
A.DIV_CODE IS NULL
AND A.ALERT_FLAG='Y' ;

Related

Case statement handling logic differently than expected

I'm trying to assign a status based on the number of IDs using a metric. This is the query I've written (and it works):
select
x.yyyy_mm_dd,
x.prov_id,
x.app,
x.metric,
x.is_100,
case
when ((x.is_100 = 'true') or size(collect_set(x.list)) >10) then 'implemented'
when ((x.is_100 = 'false') and size(collect_set(x.list)) between 1 and 10) then 'first contact'
else 'no contact'
end as impl_status,
size(collect_set(x.list)) as array_size,
collect_set(x.list) as list
from(
select
yyyy_mm_dd,
prov_id,
app,
metric,
is_100,
list
from
my_table
lateral view explode(ids) e as list
) x
group by
1,2,3,4,5
However, the impl_status is incorrect for the second condition in the case statement. In the result set, I can see rows with is_100 = false, array_size between 1 and 10, however the impl_status ends up being 'no contact' instead of 'first contact'. I was thinking maybe between isn't inclusive but it seems to be according to the docs.
I am curious if this works:
(case when x.is_100 or count(distinct x.list) > 10
then 'implemented'
when (not x.is_100) and count(x.list) > 0
then 'first contact'
else 'no contact'
end) as impl_status,
This should be the same logic without the string comparisons -- here is an interesting viewpoint on booleans in Hive. I also think that COUNT() is clearer than the array functionality.
Be sure you have not some hidden space in the string
when (( trim(x.is_100) = 'false') and size(collect_set(x.list)) between 1 and 10) then 'first contact'

how to prevent converting the text into boolean by the use of when statement in postgresql?

select fti.pa_serial_,fti.homeownerm_name,fti.ward_,fti.villagetole,fti.status,
ftrq.date_reporting, ftrq.name_of_recorder_reporting,
case
when fti.status='terminate' then ftrq.is_the_site_cleared ='1' end as is_the_site_cleared from fti join ftrq on ftrq.fulcrum_parent_id = fti.fulcrum_id
Here, is_the_site_cleared is text type of column which is converted into boolean by the when statement written and hence does not print as 1 and takes as true. I explicitly used print '1'. But this also did not work. My aim is to display '1' in the column 'is_the_site_cleared' when the value of fti.status='terminate'. Please help!!!
How about using integers rather than booleans?
select fti.pa_serial_, fti.homeownerm_name, fti.ward_,
fti.villagetole, fti.status, ftrq.date_reporting,
ftrq.name_of_recorder_reporting,
(case when fti.status = 'terminate' -- and ftrq.is_the_site_cleared = '1'
then 1 else 0
end) as is_the_site_cleared
from fti join
ftrq
on ftrq.fulcrum_parent_id = fti.fulcrum_id ;
From the description, I cannot tell if you want to include the condition ftrq.is_the_site_cleared = '1' in the when condition. But the idea is to have the then and else return numbers if that is what you want to see.

SQL Subquery to replace all values

I have a query which returns a bunch of different data, however I want to have it replace all the values upon a certain condition.
What I have written below kind of gives me the result I want but not really. It creates a new column instead of replacing the other one:
SELECT
CASE
WHEN T4.[U_DestType] = '6'
THEN (SELECT
'Company Limited' AS [ShipToCode]
)
END AS [ShipToCode],
T2.[ShipToCode],
T6.[StreetS],
T6.[StreetNoS],
T6.[CityS],
T6.[ZipCodeS],
T6.[CountryS],
T5.[LicTradNum],
T2.[CardCode],
T4.[Phone1],
T4.[E_Mail],
T4.[U_DestType],
CASE
WHEN T4.[Country] = 'GB'
THEN 'EN'
ELSE T4.[Country]
END AS [Country],
T4.[U_ShortName]
FROM[...]
The end goal is to replace all of the columns with some preset values instead of just ShipToCode as above.
I tried putting an EXIST subquery after FROM too but that didn't work either.
Is this possible? I'm probably missing something very obvious.
Many thanks!
You can use an ELSE in your CASE expression to combine the two "columns":
CASE
WHEN T4.[U_DestType] = '6'
THEN (SELECT
'Company Limited' AS [ShipToCode]
)
ELSE T2.[ShipToCode]
END AS [ShipToCode],
And by the way, you didn't need to use a Sub-Select. This would work just as well and is easier to read:
CASE
WHEN T4.[U_DestType] = '6' THEN 'Company Limited'
ELSE T2.[ShipToCode]
END AS [ShipToCode],

SQL to display a column value as a set value or null depending on status

below is the code I have written - what I want is when the status is equal to 'N' to display 'Export to WMS' in the column 'Export to WMS'.
If it has any other value than 'N' in the status, I want the column to still appear because some results will be at status 'N' but for those that aren't I want the value of that column to be blank.
select
m.display_order_number, m.record_create_date, l.lookup_description,m.wh_id,
m.client_code,m.order_type,m.order_date,m.UIN, m.ship_to_name,m.carrier,
(select DISTINCT 'Export to WMS'
from
t_3pl_order_master
where
status = 'N') AS "Export to WMS"
from
t_3pl_order_master m
INNER JOIN
t_3pl_lookup l on m.status = l.lookup_value AND l.lookup_type = 'Order Status';
Results I get are:
Where you can clearly see when the status is 'W' it still displays 'Export to WMS' but ideally I would want that to be blank and those with status 'N' to display 'Export to WMS'.
Hope you can help!
Use a case expression:
CASE WHEN status = 'N' THEN 'Export to WMS' END
in this way:
select m.display_order_number,
m.record_create_date,
l.lookup_description,
m.wh_id,
m.client_code,
m.order_type,
m.order_date,
m.UIN,
m.ship_to_name,
m.carrier,
CASE WHEN status = 'N' THEN 'Export to WMS' END AS "Export to WMS"
from t_3pl_order_master m
INNER JOIN t_3pl_lookup l on m.status = l.lookup_value AND l.lookup_type = 'Order Status';
see this link for details: https://docs.oracle.com/cd/B19306_01/server.102/b14200/expressions004.htm
Need the ELSE in there to make it blank. Otherwise it will be null.
CASE WHEN status = 'N' THEN 'Export to WMS' ELSE ' ' END AS "Export to WMS"
If I read your post correctly just use the case statement to handle this.
I would highly recommend using the case expressions already described in other answers. But to explain why your attempt didn't work I'll give you a fix of sorts.
select
m.display_order_number, m.record_create_date, l.lookup_description,m.wh_id,
m.client_code,m.order_type,m.order_date,m.UIN, m.ship_to_name,m.carrier,
(
select distinct 'Export to WMS'
from t_3pl_order_master m2
where m.status = 'N' /* <<--- Difference is here */
) AS "Export to WMS"
from
t_3pl_order_master m inner join
t_3pl_lookup l on m.status = l.lookup_value AND l.lookup_type = 'Order Status';
The subquery as you wrote it will always return the single value "Export to WMS" as long as there is at least one row in the entire table where status = 'N'. What you needed to do was correlate (connect) the subquery to the outer query by referring to m.status rather than just status.
Note that it would then evaluate to a null as "blank". Use coalesce() to turn that into the empty string if that's actually necessary.
Now the truth is that this is a very roundabout way of getting what you wanted although clever in the sense that you used the syntax you already knew to piece something together that was pretty close.

Error: Error converting data type varchar to numeric, using Hashbytes function in SQL

I have a legacy SSIS package that needs updating. Specifically it used to only add new records and must now update and end date or delete records as appropriate. elsewhere in the package I've been using the Hashbytes function with great success to evaluate which rows need to be updated by taking matching datasets from both databases and then comparing them as part of a conditional split. The problem I'm having revolves around a case statement in the source query:
SELECT DISTINCT
DTBL_STUDENTS.STUDENT_ID,
FTBL_TEST_SCORES.TEST_STUDENT_GRADE,
DTBL_TESTS.TEST_NAME,
DTBL_SCHOOL_DATES.DATE_VALUE AS Assessment_Date,
DTBL_SCHOOL_DATES.SIS_SCHOOL_YEAR AS Assessment_Year,
left( CASE
WHEN FTBL_TEST_SCORES.TEST_SCORE_TEXT = 'NA'
THEN CASE
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'INTE' THEN 'High'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'STRA' THEN 'Some'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'BNCH' THEN 'Low'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT IN ('High', 'Some', 'Low') THEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT
ELSE FTBL_TEST_SCORES.TEST_SCORE_TEXT
END
ELSE CASE
WHEN FTBL_TEST_SCORES.TEST_SCORE_TEXT LIKE '%.0000'
THEN REPLACE(FTBL_TEST_SCORES.TEST_SCORE_TEXT, '.0000', '')
ELSE FTBL_TEST_SCORES.TEST_SCORE_TEXT
END
END,12) AS TEST_SCORE_TEXT,
CASE
WHEN FTBL_TEST_SCORES.TEST_SCORE_TEXT = 'NA'
THEN CASE
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'INTE' THEN '1'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'STRA' THEN '3'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'BNCH' THEN '4'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT = 'High' THEN '1'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT = 'Some' THEN '3'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT = 'Low' THEN '4'
ELSE '0'
END
ELSE FTBL_TEST_SCORES.TEST_SCORE_VALUE
END AS TEST_SCORE_VALUE,
FTBL_TEST_SCORES.TEST_PERCENTILE_SCORE,
DTBL_SCHOOLS.SCHOOL_HR_ID
FROM K12INTEL_DW.DTBL_TESTS
JOIN K12INTEL_DW.FTBL_TEST_SCORES ON FTBL_TEST_SCORES.TESTS_KEY =
DTBL_TESTS.TESTS_KEY
JOIN K12INTEL_DW.DTBL_SCHOOL_DATES ON DTBL_SCHOOL_DATES.SCHOOL_DATES_KEY =
FTBL_TEST_SCORES.SCHOOL_DATES_KEY
JOIN K12INTEL_DW.DTBL_STUDENTS ON DTBL_STUDENTS.STUDENT_KEY =
FTBL_TEST_SCORES.STUDENT_KEY
JOIN K12INTEL_DW.DTBL_SCHOOLS ON DTBL_SCHOOLS.SCHOOL_KEY =
FTBL_TEST_SCORES.SCHOOL_KEY
WHERE DTBL_SCHOOL_DATES.SIS_SCHOOL_YEAR = 2014
AND DTBL_STUDENTS.STUDENT_CURRENT_DISTRICT_CODE = '2180'
AND FTBL_TEST_SCORES.TEST_STUDENT_GRADE IN ('PS', 'PK', 'KG', '01', '02',
'03', '04', '05', '06', '07', '08')
AND DTBL_TESTS.TEST_VENDOR IS NOT NULL
AND FTBL_TEST_SCORES.TEST_HIGHEST_SCORE_INDICATOR IN ('Yes', '--')
The 3 values I need to hash for comparison are:
TEST_SCORE_TEXT
TEST_SCORE_VALUE
Assessment_Date
It looks like it's choking on TEST_SCORE_VALUE in the function:
HASHBYTES('SHA1',ISNULL(#Dware.TEST_SCORE_TEXT,'')+convert(varchar(10),ISNULL(TEST_SCORE_VALUE,''))+convert(varchar(50),(ISNULL(Assessment_Date,'')))) as SourceHash
This is where I get the error "Error converting data type varchar to numeric". I've tried putting my source query into a subquery and doing a select*, (function) from that source query. I've tried putting the case statement into the hashbytes function, and I've tried using a temp table. My assumption is that it's getting the underlying value rather than the value generated by the case statement but I don't know why,or how to fix it so that I get the numeric values I'm expecting/wanting.
Many thanks for any assistance!
Assuming FTBL_TEST_SCORES.TEST_SCORE_VALUE is numeric, then look at your CASE statement that creates TEST_SCORE_VALUE. You create a string by evaluating TEST_PRIMARY_RESULT_CODE and TEST_PRIMARY_RESULT, etc, but your final ELSE statement is probably returning a numeric value (FTBL_TEST_SCORES.TEST_SCORE_VALUE).
I believe Sql Server determines the output type of the CASE statement by the last return value. (In any case, itt has an algorithm for determining the return type when individual THEN statements are mixed.)
So, it sees your CASE statement as typed to whatever FTBL_TEST_SCORES.TEST_SCORE_VALUE is, which is probably inconsistent with the earlier varchar return values of the CASE statement.
Fix that, and the HASHBYTES function should work, as is.
+convert(varchar(10),ISNULL(TEST_SCORE_VALUE,''))
Turns out that should've been:
+convert(varchar(10),ISNULL(TEST_SCORE_VALUE,0))
and then it all worked fine.