SQL literal value that is alternative to NULL - sql

Are there other special literal values besides NULL in SQL / PostgresQL?
NULL is nice in that we can interpret NULL as the concept of "nothing" (i.e. missing, not available, not asked, not answered, etc.), and data columns of any type can have NULL values.
I would like another value that I can interpret as representing another concept (here the idea of "everything"), in the same result set.
Is there another special value that I can return in a query, which like NULL doesn't type conflict?
Basically anything that doesn't throw ERROR: For 'UNION', types varchar and numeric are inconsistent in this toy query:
select 1 as numeral, 'one' as name UNION ALL
select 2 as numeral, 'two' as name UNION ALL
select NULL as numeral, NULL as name UNION ALL
select -999 as numeral, -999 as name UNION ALL -- type conflict
select '?' as numeral, 'x' as name -- type conflict
Here,
-999 doesn't work as its type conflicts with varchar columns
'~' doesn't work as its type conflicts with numeric columns
NULL doesn't work as it needs
More specifically here's my actual case, counting combinations of values and also include "Overall" rows in the same query. Generally I won't know or control the types of columns A, B, C in advance. And A, B, or C might also have NULL values which I would would still want to count separately.
SELECT A, COUNT(*) FROM table GROUP BY 1
UNION ALL
SELECT ?, COUNT(*) FROM table GROUP BY 1
and get a result set like:
A
COUNT
NULL
2
1
3
2
5
3
10
(all)
20
SELECT B, COUNT(*) FROM table GROUP BY 1
UNION ALL
SELECT ?, COUNT(*) FROM table GROUP BY 1
and get a result set like:
B
COUNT
NULL
2
'Circle'
3
'Line'
5
'Triangle'
10
(all)
20

You can use function CAST to convert the format to VARCHAR to be considered as string.

NOTE: Thanks to the comments above, I should completely rephrase this question as "How to COUNT/GROUP BY with ROLLUP using multiple columns of mixed/arbitrary/unknown types, and differentiate true NULL values from ROLLUP placeholders?"
The correct answer I believe is provided by #a_horse_with_no_name: use ROLLUP with GROUPING.
Below is is just me drafting that more completely with a revised example:
This toy example has an integer and a string
WITH table AS (
select 1 as numeral, 'one' as name UNION ALL
select 2 as numeral, 'two' as name UNION ALL
select 2 as numeral, 'two' as name UNION ALL
select NULL as numeral, NULL as name UNION ALL
select NULL as numeral, NULL as name UNION ALL
select NULL as numeral, NULL as name
)
select name, numeral, COUNT(*), GROUPING_ID()
FROM table
GROUP BY ROLLUP(1,2)
ORDER BY GROUPING_ID, name, numeral ;
It returns the following result:
numeral
name
count
grouping_id
note
NULL
NULL
3
0
both are true NULLs as grouping is 0
1
one
1
0
2
two
2
0
NULL
NULL
3
1
first is a true NULL, second is a ROLLUP
1
NULL
1
1
2
NULL
2
1
NULL
NULL
6
3
both NULLs are ROLLUPs

Related

UNION - inconsistent datatype got CLOB

I have a table that look like this
name
value
a
1
b
2
c
3
Of course not with these datas, but I will use it as an example
I need to use it as a inner join, where I can have each name as a column.
It is a defined amount of rows, so that should not be a problem
I have tried to do it as
SELECT
value AS a,
NULL as b
FROM ex
WHERE name = 'a'
UNION
SELECT
NULL as a,
value AS b
FROM ex
WHERE name = 'b'
And so on, but I get the error ORA-00932: inconsistent datatypes: expected - got CLOB
I have also tried with
SELECT
CASE WHEN name = 'a' THEN value ELSE NULL END AS a,
CASE WHEN name = 'b' THEN value ELSE NULL END AS b
FROM ex
WHERE name IN ('a', 'b')
But the result from this is of course
a
b
1
NULL
NULL
2
But I need to eliminate the NULL values, so I only have one row like
a
b
1
2
Does anybody have a good idea of how to solve this problem?
I can of course make 4 joins, but I was thinking, if it could be done in one join, as that will possibly be faster than look in the same table 4 times
I have the impression that you just want to get the value per name. Is this what you aim for:
WITH dat AS
(
SELECT 'a' AS NAME, 1 AS VALUE FROM dual UNION ALL
SELECT 'b', 2 FROM dual UNION ALL
SELECT 'c', 3 FROM dual
)
SELECT *
FROM (SELECT *
FROM dat
PIVOT (MAX(VALUE) FOR NAME IN ('a','b'))); -- list of the ones you need

query to select columns from a row in which another column has certain value only SQL

Consider the following table
id attribute
1 a
1 a
1 b
2 a
2 a
3 c
4 a
I want to select the ids that have attribute of 'a' only, ie 2 and 4.
Cant select 1 because 1 has 'a' and 'b', cant select 3 because it has 'c' only. We select 2 and 4 because it has 'a' value only.
You can use
SELECT id
FROM YourTable
GROUP BY id
HAVING MAX(attribute) = 'a' AND MIN(attribute) = 'a'
AND COUNT(*) = COUNT(attribute)
the
COUNT(*) = COUNT(attribute)
is to discard any id that have NULL attribute as well as a. Remove this if that is not the semantics you want or the column is not nullable anyway.
Please test this:
SELECT id
FROM attribute
GROUP BY id
HAVING
COUNT(DISTINCT attribute) = 1 AND MIN(attribute)= 'a';

Excluding a value when null is present in the column

I want to filter the table without the row c
column 1
column 2
a
100
b
200
c
50
null
200
Desired output
column 1
column 2
a
100
b
200
null
200
I tried
select *
from table
where column1 <> 'c'
But since I can compare with null, I'm getting the wrong output. How do I deal with this?
You need to handle the null as follows:
select * from table where column1 <> 'c' or column1 is null
Or you can use the coalesce function as follows:
select * from table where coalesce(column1,'cc') <> 'c'
Coalesce will replace the null value in column1 with the value provided as the second argument. I have used the value which is not equal to 'c' so records with column1 as null will pass this condition
ANSI SQL, DISTINCT predicate.
select *
from table
where column1 is distinct from 'c'
However, not supported by all dbms products.

Impala SQL, return value if a string exists within a subset of values

I have a table where the id field (not a primary key) contains either 1 or null. Over the past several years, any given part could have been entered multiple times with one, or both of these possible options.
I'm trying to write a statement that will return some value if there is ever a 1 associated with the select statement. There are lots of semi-duplicate rows, some with 1 and some with null, but if there is ever a 1, I want to return true, and if there are only null values, I want to return false. I'm not sure how to code this though.
If this is my SELECT part,id from table where part = "ABC1234" statement
part id
ABC1234 1
ABC1234 null
ABC1234 null
ABC1234 null
ABC1234 1
I want to write a statement that returns true, because 1 exists in at least one of these rows.
The closest I've come to this is by using a CASE statement, but I'm not quite there yet:
SELECT
a1.part part,
CASE WHEN a2.id is not null
THEN
'true'
ELSE
'false'
END AS id
from table.parts a1, table.ids a2 where a1.part = "ABC1234" and a1.key = a2.key;
I also tried the following case:
CASE WHEN exists
(SELECT id from table.ids where id = 1)
THEN
but I got the error subqueries are not supported in the select list
For the above SELECT statement, how do I return 1 single line that reads:
part id
ABC1234 true
You can use conditional aggregation to check if a part has atleast one row with id=1.
SELECT part,'True' id
from parts
group by part
having count(case when id = 1 then 1 end) >= 1
To return false when the id's are all nulls use
select part, case when id_true>=1 then 'True'
when id_false>=1 and id_true=0 then 'False' end id
from (
SELECT part,
count(case when id = 1 then 1 end) id_true,
count(case when id is null then 1 end) id_false,
from parts
group by part) t

Test data for unique and not null

How can I quickly check to see if the data from the test table 'test_table', and selected columns are unique and not null.
Summary, at the entrance gets a table name and a list of columns in the output are expected , eg . flag 1 or 0.
Table is big so unfortunately i must posibly fast execute;
select 1 from dual
where exsist (select col1,col2,col3,... from table
where col1 is not null and col2 is not null and col3....
group by col1,col2,col3.. having count(*) > 1 )
this will return 1 when one of the is true.
SELECT 1
FROM dual
WHERE EXISTS
(SELECT a, b FROM tab WHERE id=1
AND name='John'
AND (a IS NULL OR b IS NULL))
I changed your code and I have one question about it , now I have is that id must be 1 and the name 'John ' and any of verifying null must be correct, and wants to have that must be id = 1 and the name 'John ' and if there is either the value of the column is ' null'