Finding sum of empty columns in a row - sql

I want to create a column which finds count of non empty columns in a postgres table (like given below). Can u give me a head's up or a solution?

You can use GENERATED always as column. Example:
create table test (a VARCHAR (50),
b VARCHAR (50),
c VARCHAR (50),
cnt numeric GENERATED always as (
case when a is null then 0 else 1 end +
case when b is null then 0 else 1 end +
case when c is null then 0 else 1 end
) STORED);
Link: https://www.db-fiddle.com/f/fU5LLuh5gvwkKhhRbeCyh8/0

In Postgres, I would simply do:
select t.*,
((a is not null)::int + (b is not null)::int + (c is not null)::int) as cnt
from t;

If you don't want to hard-code the column names, you can use some JSON magic for this:
select a,b,c,
(select count(*) from jsonb_object_keys(jsonb_strip_nulls(to_jsonb(t)))) as num_not_null
from the_table t
jsonb_strip_nulls(to_jsonb(t)) converts the whole row into a single json value where the column names are the keys. Any null value will be removed. Then the keys are extracted using jsonb_object_keys and the number of keys returned is the number of non-null columns in that row.
Using a CASE expression as shown in EragonBY's answer or the boolean expressions in Gordon's answer will be a lot faster if you don't mind explicitly listing all column names.
Online example

Related

How to best check integrity of nvarchar fields that have been exported to xlsx files comparing to the view results?

I am using this code to check for data integrity of nvarchar/string data fields. Taking the sum from the view using code below, and comparing that to similar formula in EXCEL to see if I get the same total. Is there a better way? I am new at this.
--Aggregate Boolean fields e.g. nvarchar.
With table1 AS
(
Select
CASE WHEN (field_name) = 'Y' Then 1
WHEN field_name = 'N' Then 2
When field_name IS NULL THEN 3
ELSE field_name
END AS field_name_count
From mysqlview
)
Select SUM(field_name) AS Count
From table1
;
Or this approach
--Count characters in nvarchar column
Select
SUM(LEN(field_name)) AS Count
From mysqlview
;
I can't comment so I'll add my 2 cents here.
you seems to sum a Nvarchar field - can you update your question with the reasoning for this?
Also - in the first example you have sum on 'field_name' while the column name is 'field_name_count'
Do you try to see how many fields contain text and compare this number to your Excel data?
in that case you can count them easily by doing:
select count(1) from mysqlview where fieldname != '' and not fieldname is null
Hope I helped

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

Make MIN(column) return NULL if column contains NULL

SELECT MIN(column) FROM table;
will return minimum from nonnull elements.
I would like to write a query that will treat NULL as if it were the smallest value possible.
I have seen tricks with dates using a special value like here: https://stackoverflow.com/a/32240382/7810882
But what if the column is of type int and there is no special value that I can map NULL to?
You can do this using a case expression:
SELECT (CASE WHEN COUNT(*) = COUNT(COLUMN) THEN MIN(column) END)
FROM table;

Check if field is numeric, then execute comparison on only those field in one statement?

This may be simple, but I am no SQL whiz so I am getting lost. I understand that sql takes your query and executes it in a certain order, which I believe is why this query does not work:
select * from purchaseorders
where IsNumeric(purchase_order_number) = 1
and cast(purchase_order_number as int) >= 7
MOST of the purchar_order_number fields are numeric, but we introduce alphanumeric ones recently. The data I am trying to get is to see if '7' is greater than the highest numeric purchase_order_number.
The Numeric() function filters out the alphanumeric fields fine, but doing the subsequent cast comparison throws this error:
Conversion failed when converting the nvarchar value '124-4356AB' to data type int.
I am not asking what the error means, that is obvious. I am asking if there is a way to accomplish what I want in a single query, preferably in the where clause due to ORM constraints.
does this work for you?
select * from purchaseorders
where (case when IsNumeric(purchase_order_number) = 1
then cast(purchase_order_number as int)
else 0 end) >= 7
You can do a select with a subselect
select * from (
select * from purchaseorders
where IsNumeric(purchase_order_number) = 1) as correct_orders
where cast(purchase_order_number as int) >= 7
try this:
select * from purchaseorders
where try_cast(purchase_order_number as int) >= 7
have to check which column has numeric values only.
Currently, in a table every field is setted with nvarchar(max) Like tableName (field1 nvarchar(max),field2 nvarchar(max),field3 nvarchar(3)) and tableName has 25lac Rows.
But on manually Check Field2 Contain the numeric Values Only... How to Check With t-sql that in the Complete Column (Field2) has numeric Value or not/null value with Longest Length in the Column!

How to assign a value to a casted column in Oracle

I am wondering whether is possible to assign a value to a casted column in SQL depending on real table values.
For Example:
select *, cast(null as number) as value from table1
where if(table1.id > 10 then value = 1) else value = 0
NOTE: I understand the above example is not completely Oracle, but, it is just a demonstration on what I want to accomplish in Oracle. Also, the above example can be done multiple ways due to its simplicity. My goal here is to verify if it is possible to accomplish the example using casted columns (columns not part of table1) and some sort of if/else.
Thanks,
Y_Y
select table1.*, (case when table1.id > 10 then 1 else 0 end) as value
from table1