SQL - SELECT with inner IF or CASE - sql

Trying to have a row that will display 'YES' or 'NO' depending on values found (if a tree has been treated before the date given in argument say YES else NO).
Here's my function:
CREATE OR REPLACE FUNCTION tree_care(care_date DATE)
RETURNS TABLE(name VARCHAR(32), type VARCHAR(32), treated TEXT) AS
$$
BEGIN
RETURN QUERY
SELECT tree.name,
tree.type,
IF EXISTS (SELECT * FROM treatment
JOIN tree ON tree.name = treatment.tree_name
WHERE treatment.date < care_date) THEN
'YES'::text
ELSE
'NO'::text
END IF
FROM tree;
END;
$$
And I get the following error:
ERROR: syntax error at or near "EXISTS"
LINE 8: IF EXISTS (SELECT * FROM treatment
How does one implement an IF statement inside a SELECT?
PS: Using postgresql 9.4

IF is control flow. Use CASE because this is within a SELECT statement:
SELECT tree.name,
tree.type,
(CASE WHEN EXISTS (SELECT 1
FROM treatment
WHERE tree.name = treatment.tree_name AND
treatment.date < care_date
) THEN
THEN 'YES'::text
ELSE 'NO'::text
END) as Flag
FROM tree;
I am also guessing that you intend a correlated subquery, rather than an independent subquery.

Related

How to use Case statement in Postgresql?

This is my SQL Query
CASE WHEN (1>2) THEN(
select * from rate limit 10
)
ELSE
(
select * from rate limit 1
)
When I use Case statement like above , I can get error like below.
ERROR: syntax error at or near "CASE"
LINE 2: CASE WHEN (1>2) THEN(
^
SQL state: 42601
Character: 2
Can anyone help me to solve this
Put a SELECT in front of the CASE statement. Also, you need an END after the last statement of the CASE. You need a place for the result of the CASE expression to be stored. The examples in the documentation are not executing statements that return a value; just variable assignment. So you don't need a SELECT there. If you don't care about the return from the overall query, you can use PERFORM instead of SELECT.
SELECT CASE
WHEN 1 > 2 -- always false
THEN (SELECT * FROM rate LIMIT 10)
ELSE (SELECT * FROM rate LIMIT 1)
END
;
You can also assign the result of the subqueries to a variable if this CASE is defined inside of a function.
DO
$$
DECLARE
rec RECORD;
BEGIN
CASE WHEN 1 > 2
THEN (SELECT * INTO rec FROM rate LIMIT 10)
ELSE (SELECT * INTO rec FROM rate LIMIT 1)
END
;
END;
$$ LANGUAGE PLPGSQL;

Use result from case statement in another case statement in oracle

I have a view which contains a cast statement for one column. This cast statement contains a case statement. This statement works. The result of this statement is 1, 2, or 3.
From here, I need to use the result from the previous case statement (I used a WITH statement and it doesn't work) to determine the value of the column. A simple case statement that assigns yes, no or null to the above statement's value (1,2, or 3)
ANY help is appreciated. Thank you.
Example using pseudo-code:
CAST (
WITH case_output
AS(
SELECT
CASE
WHEN EXISTS
(select from table where blah blah)
THEN
(select column from that table)
ELSE
(select from some another table)
END
)
CASE
WHEN case_output = 1
THEN 'Yes'
WHEN case_output = 2
THEN 'No'
else
NULL
AS VARCHAR2 (10))
column_name,
.... [rest of query]
You're mixing up the query name and the column name of the WITH clause. For example, it's
WITH my_query AS (SELECT c1 AS my_column FROM t1)
SELECT my_column FROM my_query;
Secondly, you'll always need a FROM clause in Oracle's SQL. Use the dummy table DUAL as stand-in:
SELECT CASE WHEN ... THEN END AS my_column
FROM DUAL;
Minimal working example:
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c2 INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
WITH case_query AS (
SELECT CASE WHEN EXISTS (SELECT * FROM t1 WHERE c1=100)
THEN (SELECT c1 FROM t1)
ELSE (SELECT c2 FROM t2)
END AS case_output
FROM dual)
SELECT CASE case_output
WHEN 1 THEN 'Yes'
WHEN 2 THEN 'No'
ELSE NULL
END second_case_output
FROM case_query;

SQL function gives error in some cases, why?

I have the following function which is run for each row as we generate data. If i run the function on a separate entry it works, but it gives error in the compilation process, so there must be some rows which break it, but I cant see what it could be.. Is there anything wrong with the syntax or something i'm not thinking about here? Any help or tips is appreciated greatly
DROP FUNCTION IF EXISTS xx__calc_date;;
CREATE FUNCTION xx_calc_date(date INT, id INT, esId INT)
RETURNS DATE
DETERMINISTIC
BEGIN
IF date IS NULL OR date = 0 THEN
RETURN NULL;
ELSE -- this is where the error lies
IF(SELECT COUNT(b.TimeSort) FROM Booking b
WHERE b.BookingId IN (SELECT DISTINCT e.BookingId
FROM xx.Events e
WHERE e.id = id AND e.esId = esId)
AND TimeSort < 86400) > 0
THEN
RETURN STR_TO_DATE(date, '%Y%m%d');
ELSE
RETURN DATE_ADD(date, INTERVAL 1 DAY);
END IF;
END IF;
END;;
e.id = id is always true.
When in a subquery, you can leave off the table qualification for the inner table, not for the outer.
Suggest using EXISTS ( SELECT 1... ) instead of ( SELECT COUNT(*) ... ) > 0 )
The expression that seems to be doing two "existance" checks. Consider using a JOIN for such.

Only one expression can be specified in the select list w

I am having problem in part of my code anyway to do this
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS. The update part is working but how to use insert into to calculate if a condition is not meant it will insert.
IF
/* CHECKLIST TO UPDATE*/
(NOT EXISTS
(SELECT *
FROM ENERGY.D_ENERGY_REFERENCE D_ENERGY_REFERENCE
,ENERGY.D_CHECK_LIST D_CHECK_LIST
WHERE D_ENERGY_REFERENCE.ID = D_CHECK_LIST.ID
AND D_ENERGY_REFERENCE.REFERENCE = 19051
)
)
BEGIN
INSERT INTO DB.D_ENERGY_REFERENCE(ID, REFERENCE_NO, REFERENCE,VALUE_INTEGER)
(SELECT ID,
(SELECT ISNULL(MAX(REFERENCE_NO), 0) + 1 FROM DB.D_ENERGY_REFERENCE),
19051, (SELECT D_CHECK_LIST.ID,
CASE
WHEN CAST(COUNT(CASE WHEN D_CHECK_LIST.EVALUATION NOT IN (0,1) THEN EVALUATION ELSE NULL END) AS FLOAT) = 0 THEN NULL
ELSE
(
CAST(COUNT(CASE WHEN D_CHECK_LIST.EVALUATION IN (2, 3, 50001, 50003, 50004, 50005, 50006, 50020, 50027, 50028) THEN EVALUATION ELSE NULL END) AS FLOAT)
/
CAST(COUNT(CASE WHEN D_CHECK_LIST.EVALUATION NOT IN (0,1) THEN EVALUATION ELSE NULL END) AS FLOAT)
) * 100
END FROM DB.D_CHECK_LIST
GROUP BY D_CHECK_LIST.ID)
FROM DB.D_ENERGY_REFERENCE D_ENERGY_REFERENCE
WHERE D_ENERGY_REFERENCE.ID = ID AND D_ENERGY_REFERENCE.REFERENCE = 19051
GROUP BY D_ENERGY_REFERENCE.ID
)
END
Can you please check this following part in the sub query of your script-
.......
19051,
(
SELECT
D_CHECK_LIST.ID, -- This is the column 1
CASE
WHEN -- Here you are generating column 2 in the sub query
......
)
Here you are selecting 2 column - one is "D_CHECK_LIST.ID" and other one is generation through CASE WHEN statement. I think you should SELECT any 1 column from those 2 column. If both are required, you can use separate Sub query for that.
The ERROR code "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS" is self explanatory that you can not implement a Sub Query with more than 1 column selected unless the Sub Query is using inside EXISTS method.

SQL case statement: Return specified string if null else return select value

Below is an excerpt from my sql code, I am trying to return a string 'Off-Campus' if the value from select statement is null. If the value is not null, I want to return the value itself. However, I am getting an error:ORA-00904: "SITE_DESC": invalid identifier
00904. 00000 - "%s: invalid identifier"
Please advice on how I can go about this.
WHEN 'S' THEN (
case when(SELECT
site_desc
FROM
building
WHERE
site_code = (
SELECT
code
FROM
table2
WHERE
name = 'code'
)
) is null then 'Off-Campus' else site_desc end
)
WHEN 'F' THEN (
.... ...... .......
)
Try COALESCE:
WHEN 'S'
THEN
COALESCE(SELECT
site_desc
FROM
building
WHERE
site_code = (
SELECT
code
FROM
table2
WHERE
name = 'code'
),'Off-Campus')
You can use COALESCE:
WHEN 'S' THEN (
COALESCE(SELECT site_desc
FROM building
WHERE site_code IN (SELECT code
FROM table2
WHERE name = 'code'),
'Off-Campus')
Or:
WHEN 'S' THEN (
COALESCE(SELECT site_desc
FROM building
WHERE site_code = (SELECT TOP 1 code
FROM table2
WHERE name = 'code'),
'Off-Campus')
The difference between these two is how you handle the innermost subquery, since it's in your where clause you can either test that your value site_code is IN the results, or guarantee one result by only taking the TOP 1 and testing for equality. Doing either is good practice even if you can guarantee only one name = 'code' in table2. The first option is likely to be more useful, as it will return all codes for name='code' and test if site_code is in the results.
COALESCE(expression [,... expressionN]) goes through the expressions passed in from left to right, evaluating each until it has none left to evaluate or finds one that returns a value other than null. You can pass any number of arguments to it and it will return the first one that is not null. In your case the second expression is a hard coded string and the first is a subselect which may return null.
You could write this using coalesce():
WHEN 'S'
THEN coalesce( (SELECT site_desc
FROM building
WHERE site_code = (SELECT code FROM table2 WHERE name = 'code')
), 'Off-Campus'
)
I can't say I'm a fan of the nested subquery, so there might be a simpler way to express the logic.