Select from table where value can be null - postgresql

I try to select from one table like this:
SELECT * FROM table1 where id=311
and date BETWEEN '2012-09-01' And '2012-09-09'
and col2='a'
and (col3 ='m'
or col3 ='n'
or col3=' ' )
ORDER BY date
In the table I have situation where col3 has values 'm', 'n' or null, but this select doesn't return rows where col3 has a null value

NULL is something other than ' ' use col3 is null

There is three-valued logic in database:
TRUE, FALSE, NULL(unknown)
col3 ='' is a true condition,
col3 is null is an unknown condition.
They are different.
so you must use
col3 is null
You may reference Wikipedia's "NULL" entry.

NULL is not equal to 'm' , 'n' or ' ' . NULL isn't even equal to NULL. Use:
SELECT * FROM table1 where id=311
and date BETWEEN '2012-09-01' And '2012-09-09'
and col2='a'
and (col3 ='m'
or col3 ='n'
or col3 IS NULL)
ORDER BY date

SELECT *
FROM table1
where
id=311
and date BETWEEN '2012-09-01' And '2012-09-09'
and col2='a'
and (
col3 ='m'
or col3 ='n'
or col3 is null
)
ORDER BY date

Here is a nice trick to avoid the OR list, and to also avoid the OR IS NULL:
SELECT *
FROM table1
WHERE id=311
AND zdate BETWEEN '2012-09-01' AND '2012-09-09'
AND col2='a'
AND COALESCE(col3, 'm') IN ('m', 'n' )
ORDER BY zdate
;

Related

Count null values in each column of a table : PSQL

I have a very big table but as an example I will only provide a very small part of it as following:-
col1 col2 col3 col4
10 2 12
13 4 11
0 1
3 5 111
I know how to find null values in one column. What I want to find is how many null values are there in each column just by writing one query.
Thanks in advance
You can use an aggregate with a filter:
select count(*) filter (where col1 is null) as col1_nulls,
count(*) filter (where col2 is null) as col2_nulls,
count(*) filter (where col3 is null) as col3_nulls,
count(*) filter (where col4 is null) as col4_nulls
from the_table;
I think you can generate this query on the fly. Here is an example of one way you can approach it:
CREATE OR REPLACE FUNCTION null_counts(tablename text)
RETURNS SETOF jsonb LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT to_jsonb(t) FROM (SELECT ' || (
SELECT string_agg('count(*) filter (where ' || a.attname::text || ' is null) as ' || a.attname || '_nulls', ',')
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = tablename::regclass
AND a.attnum > 0
AND a.attisdropped = false
) || ' FROM ' || tablename::regclass || ') as t';
END
$func$;
SELECT null_counts('your_table') AS val;

Assign a Value to a New Field Depending on Which Existing Field Has A String Match

My data looks something like the following
Col1 COl2 Col3 COl4 COl5
Yes No No No No
No Yes No No No
And I want to create a new column as follows:
Col1 COl2 Col3 COl4 COl5 NEW_FIELD
Yes No No No No Col1
No Yes No No No Col2
Whereby the new field takes the name of the field where 'Yes' is matched (it only occurs in one of the columns between Col1 and Col5).
I believe I can do this with a CASE function but as I have approximately 10 columns, the syntax gets a little unwieldy and i'm wondering if there is a cleaner MIN() type function across fields?
You can get the first value using coalesce() and case:
select t.*,
(coalesce(case when col1 = 'Yes' then 'col1' end,
case when col2 = 'Yes' then 'col2' end,
case when col3 = 'Yes' then 'col3' end,
case when col4 = 'Yes' then 'col4' end,
case when col5 = 'Yes' then 'col5' end
)
) as new_field
Actually, coalesce() is not needed:
select t.*,
(case when col1 = 'Yes' then 'col1'
when col2 = 'Yes' then 'col2'
when col3 = 'Yes' then 'col3'
when col4 = 'Yes' then 'col4'
when col5 = 'Yes' then 'col5'
) as new_field
This does not seem particularly "unwieldy".

SELECT Columns WHERE one column Is Distinct?

Can anyone help me with the query ?
I've tried the following but it comes up with an error
SELECT Column1, Column2, Column3 FROM Table WHERE [Column1] NOT IN
(SELECT [Column1] FROM Table GROUP BY [Column1] HAVING COUNT([Column]) > 1)
Invalid MEMO, OLE, or Hyperlink Object in subquery [Column1].
Use Group By with Having clause:
SELECT Column1, MIN(Column2)AS Column2, MIN(Column3)AS Column3
FROM dbo.Table
GROUP BY Column1
HAVING ( COUNT(Column1) = 1 )
Should work since there's only one row per "group".
Your original query should work you just had column instead of column1.
SELECT Column1, Column2, Column3 FROM TableName WHERE [Column1] NOT IN
(SELECT [Column1] FROM TableName GROUP BY [Column1] HAVING COUNT(Column1) > 1)
see: http://sqlfiddle.com/#!3/d99a8/5/0
As far as i get , you need all data where [Column1] is unique (appear just one time)
DECLARE #x TABLE (col1 INT, col2 INT, col3 INT)
INSERT INTO #x
( [col1], [col2], [col3] )
VALUES ( 1, 2, 3 )
,( 1, 4, 5 )
,( 2, 6, 7 )
SELECT * FROM #x
SELECT col1, col2 , col3 FROM #x
WHERE col1 NOT IN
( SELECT [col1] FROM #x GROUP BY [col1] HAVING COUNT(*) > 1 )

PostgreSQL row to string

I have a result from a query like the below, which does not have a fixed number of columns
ID COL1 COL2 COL3 COL4
-------------------------------------
1 VAL11 VAL12 VAL13 VAL14
2 VAL21 VAL22 VAL23 VAL24
Now I want the result to be something like this.
RESULT
-----------------------------------------------------
ID:1, COL1:VAL11, COL2:VAL12, COL3:VAL13, COL4:VAL14
ID:2, COL1:VAL21, COL2:VAL22, COL3:VAL23, COL4:VAL24
Please help.
The quick and dirty way, but without the column names and including NULL values:
SELECT tbl::text
FROM tbl;
The slow & sure way:
SELECT array_to_string(ARRAY[
'ID:' || id
,'COL1:' || col1
,'COL2:' || col2
], ', ') AS result
FROM tbl;
If a column holds a NULL value, it will be missing in the result. I do not just concatenate, because NULL values would nullify the whole row.
array_to_string() makes sure that commas are only inserted where needed.
PostgreSQL 9.1 introduced the new function concat_ws() (much like the one in MySQL) with which we can further simplify:
SELECT concat_ws(', '
'ID:' || id
,'COL1:' || col1
,'COL2:' || col2
) AS result
FROM tbl;
SELECT
'ID:' ||coalesce(id::text, '<null>')
||', '||'COL1:'||coalesce(col1::text, '<null>')
||', '||'COL2:'||coalesce(col2::text, '<null>')
FROM tbl;
You can use this SQL to generate the first one for you (in case there're lot's of columns):
SELECT E'SELECT \n'||string_agg(trim(stmt), E' \n')||E'\n FROM tbl;'
FROM (SELECT
CASE WHEN a.attnum > 1 THEN $$||', '||$$ ELSE '' END ||
$$'$$||upper(a.attname)||$$:'||coalesce($$||quote_ident(a.attname)||
$$::text, '<null>')$$ AS stmt
FROM pg_attribute a, pg_class t
WHERE t.relkind='r' AND t.relname = 'tbl' AND a.attrelid = t.oid
AND NOT a.attisdropped AND a.attnum > 0) AS s;

How to write this T-SQL WHERE condition?

I've got two tables:
TableA
Col1
Col2
TableB
Col3
Col4
I want to join them together:
SELECT * from TableA join TableB ON (...)
Now, in place of ... I need to write an expression that evaluates to:
If Col3 is not null, then true iif Col1==Col3; otherwise
If Col3 is null, then true iif Col2==Col4
What would be the most elegant way to do this?
ON (Col1=Col3 OR (Col3 IS NULL AND Col2=Col4))
should do the trick (if Col3 is null, Col1=Col3 cannot evalutate to TRUE)
Try this:
SELECT *
FROM TableA
JOIN TableB
ON Col1 = Col3
OR (Col3 IS NULL AND Col2 = Col4)