Postgresql case and testing boolean fields - sql

First: I'm running postgresql 8.2 and testing my queries on pgAdmin.
I have a table with some fields, say:
mytable(
id integer,
mycheck boolean,
someText varchar(200));
Now, I want a query similary to this:
select id,
case when mycheck then (select name from tableA)
else (select name from tableB) end as mySpecialName,
someText;
I tried to run and get this:
ERROR: CASE types character varying and boolean cannot be matched
SQL state: 42804
And even trying to fool postgresql with
case (mycheck::integer) when 0 then
didn't work.
So, my question is: since sql doesn't have if, only case, how I'm suppose to do an if with a boolean field?

Your problem is a mismatch in your values (expressions after then and else), not your predicate (expression after when). Make sure that select name from tableA and select name from tableB return the same result type. mycheck is supposed to be a boolean.
I ran this query on PostgreSQL 9.0beta2, and (except for having to add from mytable to the SELECT statement as well as creating tables tableA and tableB), and it didn't yield any type errors. However, I get an error message much like the one you described when I run the following:
select case when true
then 1
else 'hello'::text
end;
The above yields:
ERROR: CASE types text and integer cannot be matched

I just ran this fine on PostgreSQL 8:
select id,
case when mycheck = true then (...)
else (...),
someText;

Related

Snowflake case statement is returning an error instead of the value specified within the ELSE clause

I need to check if one or many fields already exists in a table so I can do a merge into statement using them.
I tried this:
select sat_sector_hkey,
CASE
WHEN EXISTS(select id from hub_sector)
THEN (MERGE INTO ...)
END AS id
from sat_sector;
For testing, I used only one case statement, and replaced merge into with a THEN...ELSE values:
SELECT sat_sector_hkey,
CASE
WHEN EXISTS(select id from hub_sector)
THEN '1'
ELSE ''
END AS id
FROM sat_sector;
When this field does not exists, the query return an error instead of '':
SQL compilation error: error line 3 at position 23 invalid identifier
'ID'
I am using a CASE, because I need to check if a column exists or not, as I don't know if it exists or not due to some technicalities in our data coming from multiple sources.
Try this:
Construct an object with the full row.
Test if the constructed object has data for "ID".
create or replace temp table maybe_id
as
select 1 x, 2 id;
select *,
case
when object_construct(a.*):ID is not null
then '1'
else ''
end as id
from maybe_id a
;
Works for me - it gives 1 when the column id has data, and `` when the column doesn't exist in the table.

SQL use intermediate results

I have a column with numbers (float) that I would like to categorize and store a category as integer and as label (string). For now assume that the category is simply defined by the FLOOR(x).
This works:
SELECT salary,
FLOOR(salary) AS category_integer,
CASE WHEN FLOOR(salary) = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM test01
but I was wondering if I could use the intermediate variable 'category_integer' defined in the beginning of my query in a later part, something like this:
SELECT salary,
FLOOR(salary) AS category_integer,
CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM test01
but this is apparently not how SQL works. I've looked into Common table Expressions but got lost there. Is there a way to reuse intermediate variables in an SQL expression?
SQL Fiddle
I must have missed this but I couldn't find related questions so far.
You may resort to common table expressions - basically a query that produces a labelled result set you can refer to in subsequent queries.
Adapted to your example:
with cte as (
select salary
, floor(salary) as category_integer
from test01
)
SELECT salary
, category_integer
, CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM cte
;
Consult the reference for more details: CTE / WITH in pgSQL 9.6.
See it at work in SQL fiddle.
There are pre- and post-selection operations. For example order by and group by are post-selection instructions, distinct for example filters out duplicate results during the selection proces itself and as such duplicate results do not even enter the result set to be ordered or grouped.
When you use AS, you are telling PostgreSQL to take the result and put it in a column named category_integer in the output. You are not actually making a variable here that's available during query execution, as the result is only available after the query executes. As such, you can only do this with subselects where you have the result available as a virtual table in itself, where category_integer is a column in a table rather than a variable.
SELECT category_integer,
CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM (SELECT FLOOR(0) AS category_integer FROM test01) AS test02
https://www.postgresql.org/docs/current/static/queries-select-lists.html
https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-TABLE-ALIASES

Selecting from table to insert into another, getting a type error

I have the following query which inserts data into one table after selecting it from another.
The problem is that the data types do not match for one of the columns. I have simplified the query below.
INSERT INTO tbl.LogTable (
[SelPartNo], -- This does not match, see below
)
SELECT TOP 1
IF([SelPartNo] = 'False', NULL, [SelPartNo],
FROM tbl.MyTable
WHERE ID = '20358'
ORDER BY CreateDate DESC
The first SelPartNo is an int and the second is a VarChar. In most instances the SelPartNo for the second one (tbl.MyTable) is NULL or an integer, which I don't think will cause a problem. But in some cases the value is "False", which needs to return NULL.
I have tried an IF statement but I am doing something wrong because it's giving a syntax error and I am unsure if this is the correct approach.
Your code is syntactically incorect...
Try it with
NULLIF([SelPartNo],'False')
This function returns NULL if the two expressions are equal.
Details: https://msdn.microsoft.com/en-us/library/ms177562.aspx
I don't think IF is a function, at least not one which you can use in a SELECT statement. But CASE WHEN ... END is your friend:
INSERT INTO tbl.LogTable (
[SelPartNo]
)
SELECT TOP 1
CASE WHEN [SelPartNo] = 'False' THEN NULL ELSE [SelPartNo] END
FROM tbl.MyTable
WHERE ID = '20358'
ORDER BY CreateDate DESC

SELECT-CASE-IN-SELECT error: [SQL0115] Comparison operator IN not valid. In query db2

i have a problem in a db2 query
I tried run this query
SELECT t.* ,
CASE WHEN column in (SELECT data FROM otherTable WHERE conditions...)
then 5
else 0
end as 'My new data'
FROM table t
WHERE conditions....
But get error
[Error Code: -115, SQL State: 42601] [SQL0115] Comparison operator IN not valid.
When i change the sub-query to where statement like this
SELECT t.*
FROM table t
WHERE column in (SELECT data FROM otherTable WHERE conditions...)
Works fine
Why not work in the case statement? It is a limitation of db2?
And could make an equivalent behavior?
One way to do this is to left join to the table and check if it is not null.
In most cases this will be the fastest way because SQL servers are optimized to perform joins very quickly (but will depend on a number of factors including data model, indexes, data size, etc).
Like this:
SELECT t.* ,
CASE WHEN othertable.data is not null
then 5
else 0
end as 'My new data'
FROM table t
left join otherTable ON otherTable.column = data
WHERE conditions....
Try with using exists condition as below (put the column value in the where clause of subquery) :
SELECT t.* ,
CASE WHEN exists (SELECT data FROM otherTable WHERE conditions... and column=val)
then 5
else 0
end as 'My new data'
FROM table t
WHERE conditions....

checking for boolean true / false result in postgresql query

I am running the following sql query in my web app:
SELECT EXISTS (
SELECT id
FROM user
WHERE membership=1244)
i was expecting true (boolean data) as the result but I'm getting 't' or 'f' for false.
How do I get it to return to my lua code a standard boolean?
I found the following post:
Reading boolean correctly from Postgres by PHP
And so I tried to change my code to something like this:
SELECT EXISTS ::int (
SELECT id
FROM user
WHERE membership=1244)
or
SELECT ::INT (SELECT EXISTS (
SELECT id
FROM user
WHERE membership=1244))
But I'm getting a syntax error.
Can you tell the best way to handle this? Should I be casting the resulting 't' to a boolean somehow? or is there a way to tell postgresql to return true / false instead of 't'/'f'?
Thanks.
You are so close
SELECT EXISTS (SELECT id FROM user WHERE membership=1244)::int
Your first query do indeed return a boolean. A t is shown as the returned value of the query
select exists (select 1);
exists
--------
t
But if you check its type it is a boolean:
select pg_typeof(exists (select 1));
pg_typeof
-----------
boolean
You will have to check with the lua's postgresql driver manual how to properly handle it.
Try it with CASE
select
(case when exists (SELECT id FROM user WHERE membership = 1244)
then 1
else 0
end) as column;
my test fiddle
Your initial query is fine by itself:
SELECT id FROM user WHERE membership=1244
You just need to check if it returns a row or not.