Zero length ROW (ROW()) misbehaviour - sql

I use PostgreSQL 10.3.
The following statements give the same result: true;
SELECT ROW() IS NULL;
SELECT ROW() IS NOT NULL;
and the next one
SELECT ROW() = ROW();
gives:
"ERROR: cannot compare rows of zero length"
So, if a row is of zero length, then is it unknown, not unknown or both?
And, how can I check if a row is of zero length or not?
Tia

https://www.postgresql.org/docs/current/static/functions-comparison.html
If the expression is row-valued, then IS NULL is true when the row
expression itself is null or when all the row's fields are null, while
IS NOT NULL is true when the row expression itself is non-null and all
the row's fields are non-null. Because of this behavior, IS NULL and
IS NOT NULL do not always return inverse results for row-valued
expressions
regarding the way to tell the row attributes count. I'm not sure how to do it neat, but you can think of many monkey ways, eg:
t=# SELECT count(1) from (select json_object_keys(row_to_json(ROW(1,2,3)))) a;
count
-------
3
(1 row)
t=# SELECT count(1) from (select json_object_keys(row_to_json(ROW()))) a;
count
-------
0
(1 row)

PostgreSQL does not allow comparison of rows of zero length.
To check the size of a row, try pg_column_size:
CREATE TEMPORARY TABLE t (a TEXT, b TEXT);
INSERT INTO t VALUES ('foo','bar'),('foo','bar2');
SELECT pg_column_size(a)+pg_column_size(b) FROM t;
To check if it is zero:
SELECT pg_column_size(ROW())-24=0

Related

SQL Query : should return Single Record if Search Condition met, otherwise return Multiple Records

I have table with Billions of Records, Table structure is like :
ID NUMBER PRIMARY KEY,
MY_SEARCH_COLUMN NUMBER,
MY_SEARCH_COLUMN will have Numeric value upto 15 Digit in length.
What I want is, if any specific record is matched, I will have to get that matched value only,
i.e. : If I enter WHERE MY_SEARCH_COLUMN = 123454321 and table has value 123454321 then this only should be returned.
But if exact value is not matched, I will have to get next 10 values from the table.
i.e. : if I enter WHERE MY_SEARCH_COLUMN = 123454321 and column does not have the value 123454321 then it should return 10 values from the table which is greater than 123454321
Both the case should be covered in single SQL Query, and I have have to keep in mind the Performance of the Query. I have already created Index on the MY_SEARCH_COLUMN columns, so other suggestions are welcome to improve the Performance.
This could be tricky to do without using a proc or maybe some dynamic SQL, but we can try using ROW_NUMBER here:
WITH cte AS (
SELECT ID, MY_SEARCH_COLUMN,
ROW_NUMBER() OVER (ORDER BY MY_SEARCH_COLUMN) rn
FROM yourTable
WHERE MY_SEARCH_COLUMN >= 123454321
)
SELECT *
FROM cte
WHERE rn <= CASE WHEN EXISTS (SELECT 1 FROM yourTable WHERE MY_SEARCH_COLUMN = 123454321)
THEN 1
ELSE 10 END;
The basic idea of the above query is that we assign a row number to all records matching the target or greater. Then, we query using either a row number of 1, in case of an exact match, or all row numbers up to 10 in case of no match.
SELECT *
FROM your_table AS src
WHERE src.MY_SEARCH_COLUMN = CASE WHEN EXISTS (SELECT 1 FROM your_table AS src2 WITH(NOLOCK) WHERE src2.MY_SEARCH_COLUMN = 123456321)
THEN 123456321
ELSE src.MY_SEARCH_COLUMN
END

SQL NOT IN function not returning expected result

Total number of records in table i1450:
Total number with condition where i.BROJ is equal to field REFERENCA in other table:
Shouldn't it return difference between last two results (which is 64) when I use NOT IN in WHERE clause?
Both of columns are of varchar type.
If you have any NULL values in the REFERENCA column from the FpsPmtOrderRQ table then the NOT IN clause will not work as expected - (the reason why)
A solution is to remove NULL values from the result returned by the subselect.
SELECT COUNT(*)
FROM i1450 j
WHERE i.BROJ NOT IN (SELECT REFERENCA FROM FpsPmtOrderRQ WHERE REFERENCA IS NOT NULL)
If the sub-query returns a null value, the IN will not be true. Do NOT EXISTS instead.
select count(*)
from i1450 i
where not exists (select 1 from FpsPmtOrderRQ f
where i.broj = f.REFERENCA)
I think you need to coalesce your field to handle nulls. That is probably why you get 0.
By doing:
where coalesce(I.BROJ,'n/a') not in (select coalesce(REFERENCA,'')
or something similar, you would exclude nulls, and return a proper count.

Spark SQL: Specify column name resulting from UDF in WHERE clause

I have written a UDF function which will return a column (0 or 1) after processing 2 columns. I need to have my select query such that it returns those records for which this value is 1.
I wrote the query as below:
SELECT number, myUDF(col1, col2) as result
FROM mytable
WHERE result is not null
However it doesn't recognize the column name 'result'. Is there any special syntax needed so that it recognizes this new output column? Thanks.
CASE statement should solve the problem here:
SELECT number,
CASE when myUDF(col1, col2) = 1 then myUDF(col1, col2) END as result
FROM mytable

Is a subquery, which is returning no row, equal to NULL?

In SQL Server, if my SELECT statement in a subquery returns no row, is then the result of the subquery equal to NULL? I made some research, but I am not sure about it.
Example:
IF (SELECT TOP 1 CLMN1 FROM SOMETABLE) IS NOT NULL THEN
....
I am asking to understand the behaviour of the if-statement above.
Looks like the answer is yes:
DECLARE #Test TABLE (Id INT)
INSERT INTO #Test VALUES (1)
SELECT * FROM #Test WHERE Id = 2
SELECT CASE WHEN (SELECT * FROM #Test WHERE Id = 2) IS NULL THEN 1 ELSE 0 END
EDIT: after you updated your question I think I should add that instead of checking if there are rows with IS NULL you should use the following that can be better optimised by the server:
IF EXISTS(SELECT * FROM #Test WHERE Id = 2)
BEGIN
-- Whatever
END
NULL means no value, for example that the "box" for a certain column in a certain row is empty. NO ROW means that there are no rows.
No, NULL is a column value that indicates that the value of that column for a given row has no valid value. There would have to be a row returned by your query for that row to contain NULL column values.
A query that returns no rows just means that no rows matched the predicate you used in the query and therefore no data was returned at all.
Edit: After the question was edited, my answer doesn't address the specific case called out in the question. Juan's answer above does.

Sqlite: Why does 'select min(time) from asdftable' return a blank row when DB is empty?

This is an oddity. I have an empty SQLite DB.
When I execute select min(time) from asdftable I get a blank row back. When I execute select time from asdftable I get nothing back (which is proper).
Any ideas why this is?
Aggregate functions all return something even if nothing is found, simply because they are implicitly grouping all (any) rows in your table to get you an aggregate value. Take count for example:
sqlite> create table foo (a int not null);
sqlite> select count(a) from foo;
0
null is to min as 0 is to count where no rows are returned.
This can be a useful property. Consider the following example:
sqlite> select ifnull(min(a), "I'm null") from foo;
I'm null
If you want to filter this case so no records are returned, you can use a having clause (and make the grouping explicit):
sqlite> select min(a) as min_a from foo group by a having min_a not null;