How to write case statments - sql

I have two tables(ABC,CDE) in my Netezza. I need to write the following list of case statement to display value.
Tables and Columns:
Table name ABC:
Column: (Id(PK), Desc)
Table name CDE:
Columns: (value(like 1, 2, 3), ID(FK))
select case when value Is Not Null then 'CALIFORNIA' else ID end
from CDE
NZ displays pg atoi (I think it is unable to do the conversion for ID to varchar)
How to write CASE using NZ?

SELECT
CASE
WHEN value IS NOT NULL THEN 'CALIFORNIA'
ELSE TO_CHAR(ID)
END
FROM CDE;

Do this:
CAST(Id AS VARCHAR(50))
or
| Function | Return Type | Description |
======================================================================
| to_char(int, text) | text | converts integer to string |
Try this:
SELECT
CASE
WHEN value IS NOT NULL THEN 'CALIFORNIA'
ELSE to_char(ID, text)
END
FROM CDE;

Related

String Split Ignore Last delimiter if no data

I am string splitting some values that are comma delimited into rows.
However some values have an extra comma on the end.
Example
Userid | Value
1 | A,B,C,D,
2 | F,H
Code
select value
from string_split('A,B,C,D,',',')
Current Output
UserId | Value
1 | A
1 | B
1 | C
1 | D
1 |
Is there any way to make the string split function ignore the final comma if no data follows it?
Desired Output
UserId | Value
1 | A
1 | B
1 | C
1 | D
Using MSSQL
Just add "WHERE" sentence like this:
select value
from string_split('A,B,C,D,',',')
WHERE value <> ''
STRING_SPLIT Function doesn't support for lower version of sql server so first create a function to split the given string and join the function with your select query.Here is below sample for your expected result.
Created User defined Function
CREATE FUNCTION [dbo].[Udf_StringSplit]
(
#Userid INT,
#Value VARCHAR(1000)
)
RETURNS #Result TABLE(
Userid INT,
Value VARCHAR(10)
)
AS BEGIN
DECLARE #Data AS TABLE
(
Userid INT,
Value VARCHAR(100)
)
INSERT INTO #Data(Userid,Value)
SELECT #Userid, #Value
INSERT INTO #Result(Userid,Value)
SELECT Userid,
Split.a.value('.','nvarchar(1000)') AS Value
FROM
(
SELECT Userid,
CAST('<S>'+REPLACE(#Value,',','</S><S>')+'</S>' AS XML) Value
FROM #Data
) AS A
CROSS APPLY Value.nodes('S') AS Split(a)
WHERE Userid=#Userid AND Split.a.value('.','nvarchar(1000)') <>''
RETURN
END
GO
Sample data table
DECLARE #Data AS TABLE(Userid INT , Value VARCHAR(100))
INSERT INTO #Data
SELECT 1,'A,B,C,D,' UNION ALL
SELECT 2,'F,H'
Sql script to get the expected result
SELECT d.Userid,
f.Value
FROM #Data d
CROSS APPLY [dbo].[Udf_StringSplit] (d.Userid,d.Value) AS f
WHERE d.Userid=1
GO
Result
Userid Value
------------
1 A
1 B
1 C
1 D

Return null from SUBSTRING if substring not found

SELECT
SUBSTRING(campaign_name,CHARINDEX(‘[’,campaign_name)+1,
(((LEN(campaign_name))-CHARINDEX(‘]’,REVERSE(campaign_name)))-
CHARINDEX(‘[’,campaign_name))) as campaign_code
FROM table
This code currently gives me the substring between '[' and ']' from the field campaign_name. However, for a couple of entries in the campaign_name field there is no '[' or ']'. In these cases, the above code returns the whole string in the field. Instead I want to return NULL but at the moment I have been unable to execute this. I would love some thoughts.
SELECT
CASE WHEN CHARINDEX(‘[’,campaign_name) = 0 or CHARINDEX(‘]’,campaign_name) = 0 THEN null ELSE SUBSTRING(campaign_name,CHARINDEX(‘[’,campaign_name)+1,
(((LEN(campaign_name))-CHARINDEX(‘]’,REVERSE(campaign_name)))-
CHARINDEX(‘[’,campaign_name))) END as campaign_code
FROM table
The question doesn't specify a database engine; I'm assuming SQL Server from the syntax.
The SUBSTRING function will return NULL when one of its inputs is NULL, so we can make use of the NULLIF() function to null out fields that don't match the pattern (i.e. those for which CHARINDEX == 0).
DECLARE #WORDS TABLE (
Word VARCHAR(MAX)
);
INSERT INTO #WORDS VALUES ('abcdefghijklmnopqrstuvwxyz');
INSERT INTO #WORDS VALUES ('xyzzy');
INSERT INTO #WORDS VALUES ('la de dah');
INSERT INTO #WORDS VALUES ('redefine');
INSERT INTO #WORDS VALUES ('definitely');
DECLARE #SEARCHSTRING VARCHAR(MAX) = 'def';
SELECT
SUBSTRING(Word,NULLIF(CHARINDEX(#SEARCHSTRING,Word),0),LEN(#SEARCHSTRING)) as Result
FROM #WORDS
+------+
|Result|
+------+
| def |
| NULL |
| NULL |
| def |
| def |
+------+

Convert INT column values to an empty string using ISNULL

I need to convert column ID of INT data type to a empty string ['']. I should not modify the source column data type, but need to convert it in my transformation in the other table. The ID column is "nullable" as it has null in it.This is my code.
CREATE TABLE #V(ID INT) ;
INSERT INTO #V
VALUES (1),(2),(3),(4),(5),(NULL),(NULL) ;
SELECT CASE WHEN CAST(ISNULL(ID,'') AS VARCHAR(10)) = '' THEN '' ELSE ID END AS ID_Column
FROM #V;
this returns:
ID_Column
1
2
3
4
5
NULL
NULL
when I modify my CASE statement it as follows:
CASE WHEN CAST(ISNULL(ID,'') AS VARCHAR(10)) = '' THEN '' ELSE ID END AS ID_Column
it returns:
ID_Column
1
2
3
4
5
0
0
Is this what you want?
select coalesce(cast(id as varchar(255)), '')
from #v;
You have to turn the entire result column into a single column. If you want a blank value, then the type is some sort of character string.
In your examples, the else id means that the result from the case is an integer, which is why you are getting either 0 or NULL.

Postgresql: How can I inspect which arguments to a procedure have a default value?

I have defined a stored procedure in Postgresql:
create or replace function
test1(arg1 text, opt1 text default 'default value')
returns text as $$ select $1 || ' ' || $2; $$ language sql;
I would like to inspect this function definition to find out:
Which parameters have a default value
(bonus) What the default values are
I tried comparing information_schema.parameters records for the example:
select * from information_schema.parameters;
(using diff -y --suppress-common-lines)
-[ RECORD 4808 ]---------+----------------------- | -[ RECORD 4809 ]---------+-----------------------------------
ordinal_position | 1 | ordinal_position | 2
parameter_name | arg1 | parameter_name | opt1
dtd_identifier | 1 | dtd_identifier | 2
The only place I have managed to find reference to the default value is in the pg_proc table:
select proargdefaults from pg_proc where proname = 'test1' ;
-[ RECORD 1 ]--+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
proargdefaults | ({CONST :consttype 25 :consttypmod -1 :constcollid 100 :constlen -1 :constbyval false :constisnull false :location 62 :constvalue 10 [ 40 0 0 0 119 105 98 98 108 101 ]})
That bit in square brackets at the end seems to contain the default in some kind of internal format:
(using Python)
>>> d="68 0 0 0 100 101 102 97 117 108 116 32 118 97 108 117 101"
>>> "".join([chr(int(a)) for a in d.split()])
'D\x00\x00\x00default value'
My question: Is there a better way to inspect this function to find out about default parameters?
Update I am looking for something that produces output like...
-[ RECORD 1 ]----+----------------------------
arg_index | 1
arg_name | arg1
arg_has_default | f
arg_default_text | <null>
-[ RECORD 2 ]----+----------------------------
arg_index | 2
arg_name | opt1
arg_has_default | t
arg_default_text | default value
You can select the optional arguments from pg_proc, but you probably won't be able to parse their default values' expressions on PostgreSQL's side (because they can have different types).
select proargnames[pronargs-pronargdefaults+1:pronargs] optargnames,
pg_get_expr(proargdefaults, 0) optargdefaults
from pg_proc
where proname = 'test1'
SQLFiddle
EDIT: found a way to easily parse the default values into a json value (keys are the argument names, values are their default values' json representation):
create or replace function proargdefaultsjson(proc pg_proc) returns json
language plpgsql
as $function$
declare
expr_parsed record;
begin
execute format(
'select * from (values (%s)) v(%s)',
pg_get_expr(proc.proargdefaults, 0),
array_to_string(array(
select quote_ident(n)
from unnest(proc.proargnames[proc.pronargs-proc.pronargdefaults+1:proc.pronargs]) n
), ',')
) into expr_parsed;
return row_to_json(expr_parsed);
end
$function$;
This function should work in PostgreSQL 9.2+: SQLFiddle
EDIT 2: you can achieve something similar with the hstore module, if you return with hstore(expr_parsed); (this case you will end up with each default expression's text representation).
You can use pg_get_function_arguments() to retrieve the definition of the parameters:
SELECT pg_get_function_arguments(p.oid) as parameters
FROM pg_proc p
JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE p.proname = 'test1'
AND n.nspname = 'public';
This will return arg1 text, opt1 text DEFAULT 'default value'::text for your example.
SELECT A.ordinal_position AS seq
, A.parameter_name
, A.data_type
, default_value
, CASE
WHEN position('NULL' in LTRIM(default_value)) > 0 THEN 'N'
ElSE 'Y'
END AS defaultYN
FROM (
SELECT routines.routine_name,
parameters.*
FROM information_schema.routines
LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
WHERE routines.routine_name = 'yourProcName'
ORDER BY routines.routine_name, parameters.ordinal_position
) A
INNER JOIN (
SELECT unnest(optargnames) as parameter_name
, unnest(string_to_array(optargdefaults, ', ')) as default_value
FROM (
SELECT proargnames[pronargs-pronargdefaults+1:pronargs] optargnames,
pg_get_expr(proargdefaults, 0) optargdefaults
FROM pg_catalog.pg_proc
WHERE proname = 'yourProcName'
) BBBB
) B
ON A.parameter_name = B.parameter_name
select
a.parameter_name,
case when typeall is null
then types
else
typeall
end as type,
coalesce(a.parameter_mode,'i') as parameter_mode,
coalesce(b.optargdefaults,'') as default
from(
select
unnest(proargnames) as parameter_name,
unnest(proargmodes) as parameter_mode,
regtype(unnest(proallargtypes)) as typeall,
regtype(unnest(proargtypes)) as types
FROM pg_catalog.pg_proc
WHERE proname = 'your_function or sp name'
-- AND prokind = 'f'
) a
left join(
-- search for the parameter default
SELECT
unnest(proargnames[pronargs-pronargdefaults+1:pronargs] )optargnames,
unnest(string_to_array(pg_get_expr(proargdefaults, 0)::text,',')) optargdefaults
FROM pg_catalog.pg_proc
WHERE proname = 'your_function or sp name'
) b on b.optargnames = a.parameter_name
where parameter_mode in('i','o','b') or parameter_mode is null

How to create a ternary condition on a bit field in T-SQL

I have a SQLExpress table that includes a bit field for storing TRUE/FALSE state.
Something like:
+----+---------+
| ID | IsAlive |
+----+---------+
| 1 | 1 |
| 2 | 0 |
| 3 | NULL |
| 4 | 1 |
+----+---------+
Using that table as our example, I want to create one Stored Procedure that will do any one of the following:
Retrieve all records.
Retrieve only the records with IsAlive=1.
Retrieve only the records with IsAlive=0 or NULL.
I am trying to think of how I can create my query without having to write IF/ELSE conditions - It seems to me there is a better/cleaner way than to do something like this:
-- The ternary logic...
-- 0 or NULL retrieves records where IsAlive = 0 or NULL
-- 1 retrieves records where IsAlive = 1
-- Otherwise return all records
-- sproc .....
#IsAlive tinyint = 2 -- Return all records by default
AS
BEGIN
IF(#SentToNTService = 0 OR #SentToNTService = 1)
BEGIN
SELECT *
FROM MyTable
WHERE IsAlive = #IsAlive;
END
ELSE -- Lame redundancy
BEGIN
SELECT *
FROM MyTable
END
END
Is there another way of creating the same results without having to create two different queries as I did above?
2 suggestions of how to do this:
Assuming your variable #isalive is declared as 'bit' as well (which is should be)
SELECT * FROM #t
WHERE #isalive is null or #isalive = coalesce(isalive, 0)
If you want to use a 'bit compare' solution that doesn't require #isalive to be 'bit' (it will work for bit as well as tinyint)
SELECT * FROM #t
WHERE coalesce((1-coalesce(isalive, 0)) ^ #isalive, 1) > 0
Second solution is for nerds like me. Some hardcore people may find it interesting (or at least amusing) as I think it offer the best possible performance (please, someone correct me if i am wrong). It is a powerful solution but hard to read.
This will do what you want:
SELECT *
FROM MyTable
WHERE COALESCE(IsAlive, 0) = COALESCE(#IsAlive, COALESCE(IsAlive, 0))
Based on the value of #IsAlive:
If NULL, then will return everything (because the condition is always true)
If 1, then will return those rows with IsAlive = 1
If 0, then will return those rows with IsAlive = 0 or NULL
COALESCE is a function that returns it's first argument, unless it's NULL, in which case it returns its second argument.
So the LHS returns 0 if IsAlive is NULL or 0 and 1 if IsAlive is 1.
The RHS returns the same when the stored procedure argument #IsAlive is NULL and just returns the #IsAlive argument otherwise.
EDIT:
This assumed that #IsAlive is BIT. In the case of tinyint you can add a case statement:
SELECT *
FROM MyTable
WHERE COALESCE(IsAlive, 0) = CASE #IsAlive
WHEN 0 THEN 0
WHEN 1 THEN 1
ELSE COALESCE(IsAlive, 0)
END
try this:
SELECT * FROM MyTable WHERE ISNULL (IsAlive, 0) = ISNULL (#IsAlive, 0)
UNION
SELECT * FROM MyTable WHERE ISNULL (#IsAlive, 0) > 1
This isnt exact, but pretty close to what you can do:
SELECT *
FROM MyTable
WHERE CASE #IsAlive
WHEN 0 THEN IsAlive = #IsAlive
WHEN 1 THEN IsAlive = #IsAlive
ELSE 1=1 --dummy true value, when null or anything else
END
Something like this should also work.
SELECT *
FROM MyTable
WHERE (#IsAlive = 0 and IsAlive=0)
OR (#IsAlive =1 and IsAlive =1)
OR (#IsAlive is null)