SQL query for displaying record with maximum number of non-empty fields - sql

I am looking for a query/set of SQL queries that will give me the record ID of the record which has the "maximum number of non-empty/non-null fields".
I was looking into count() and max() functions, but they seem to be solving problems for the same column, but not for the same row (which is what I am looking for).
Please help.

You could order by the amount of non-empty fields:
select top 1 Record_ID
from YourTable
order by
case when isnull(col1,'') <> '' then 1 else 0 end +
case when isnull(col2,'') <> '' then 1 else 0 end +
case when isnull(col3,'') <> '' then 1 else 0 end +
...
case when isnull(colN,'') <> '' then 1 else 0 end
This is SQL Server syntax. If you're using another database, please amend your question.

Related

Count(*) return 1 or zero

In one of the usecase I need a query which should return 1 based on condition also if not match it should return 0
In Descpriont column if the 'SAP' count is exactly 1 then the query should return 1 else it should return 0
Note : There might be a chance that SAP could be present any number of times in Description column.
Could someone help me out here !!
Thanks.
I tried below query :
SELECT 1 from TableName where Description ='SAP' having count(*)>1
It is returning 1 but not return 0 if the count is more than 1 or no match found.
Use CASE WHEN to decide whether to show 0 or 1.
select case when count(*) = 1 then 1 else 0 end as sap_count_is_1
from mytable
where description = 'SAP';
use case when
select
case when sum(case when description='SAP' then 1 else 0 end)=1 then 1 else 0 end from table_name

Count column with specific condition

How can i count columns that hold particular values - but have it as a grand-total.
table data:
Code No
1 *
2 -
3 4
4
If for example i wanted to count how many rows had * and - and space
I could do
Case when No = '*'
Then COUNT(No)
when No = '-' then count(No)
when No = '' then count(No)
else 0 end as 'Count'
but this returns 4
http://sqlfiddle.com/#!9/f73409/4
I would want this to return 3
Any help would be appreciated
Use IN:
select Sum(Case when No IN ('*', '-', '') then 1 else 0 end) as Count
from Table1
See Fiddle.
Standard SQL has a particular feature for that: the filter clause that follows aggregates.
Unfortunately, it is not very widely supported (mainly PostgreSQL).
There is an easy workaround using case however:
COUNT(CASE WHEN <condition> THEN 1 END)
This works because the implied else null clause of case and because count does not count null.
More about the filter clause and ways to mimic it: http://modern-sql.com/feature/filter

SQL - Command to get Id's with unique flags from multiple flags

ID Risk_1 Risk_2 Risk_3 Risk_4
XYZ Yes Yes Yes
ABC Yes
PQR Yes Yes
As you can see from the above table There are IDs that have multiple risks associated with them. I want to get an output of IDs where only one risk is associated with them.
In the case above I want all IDs which have only risk_1 so the result should be ABC.
How can I get this done using SQL?
Assuming that Risks are nullable.
SELECT ID
FROM tableName
WHERE CASE WHEN Risk_1 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Risk_2 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Risk_3 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Risk_4 IS NOT NULL THEN 1 ELSE 0 END = 1
SQLFiddle Demo
if however they are empty string,
SELECT ID
FROM tableName
WHERE CASE WHEN Risk_1 <> '' THEN 1 ELSE 0 END +
CASE WHEN Risk_2 <> '' THEN 1 ELSE 0 END +
CASE WHEN Risk_3 <> '' THEN 1 ELSE 0 END +
CASE WHEN Risk_4 <> '' THEN 1 ELSE 0 END = 1
SQLFiddle Demo
That will work with NULLs, empty strings, or values other than Yes (e.g. No)
SELECT ID
FROM Table1
WHERE COALESCE(Risk_1, 'No') = 'Yes' AND
COALESCE(Risk_2, 'No') <> 'Yes' AND
COALESCE(Risk_3, 'No') <> 'Yes' AND
COALESCE(Risk_4, 'No') <> 'Yes'
sqlfiddle
If the value of risks are only 'Yes' then below query will work
select ID from table where risk1||risk2||risk3||risk4='Yes'
If the value of risks are only 'Yes' and the empty risks have spaces instead of nulls then below query will work
select ID from table where replace(risk1||risk2||risk3||risk4,' ','')='Yes'
If you altered your schema so your table had columns ID and risk_type with a row for each risk type, you could have a query like this:
SELECT ID
FROM Table1
GROUP BY ID
HAVING COUNT(*) = 1
SQLFiddle
re-edit: modified to no longer specify which one risk type they have

SQL: sort by number of empty columns

I have a SQL query which displays a list of results. Every row in my database has about
20 columns and not every column is mandatory. I would like the result of the SQL query to be
sorted by the number of filled in columns. The rows with the least empty columns at the top, the ones with the most empty columns at the bottom. Do any of you guys have an idea how to do this?
I thought about adding an extra column to the table which if updated every time the user edits their row, this number would indicate the number of empty columns and I could sort my list with that. This however, sounds like unnecessary troubles, but maybe there is no other way? I'm sure somebody on here will know!
Thanks,
Sander
You can do it in just about any database with a giant case statement:
order by ((case when col1 is not null then 1 else 0 end) +
(case when col2 is not null then 1 else 0 end) +
. . .
(case when col20 is not null then 1 else 0 end)
) desc
You could order by the amount of empty columns:
order by
case when col1 is null then 1 else 0 end +
case when col2 is null then 1 else 0 end +
case when col3 is null then 1 else 0 end +
...
case when col20 is null then 1 else 0 end
(Note the + at the end of the lines: it's only one column with the integer count of empty fields, sorted in ascending order.)

SQL Query - Can I compare using LEN in SELECT clause?

I basically want to do this:
SELECT HasComments = CASE (LEN(Comments) > 1) WHEN 1 THEN 1 ELSE 0 END FROM TableName
In other words, return a boolean telling me whether the length of Comments is greater than 1. This gives me a syntax error.
How can I accomplish this?
SELECT HasComments = CASE WHEN LEN(Comments) > 1 THEN 1 ELSE 0 END
FROM TableName
A better way would be to make Comments NULLable and check for that. Indexes could then be leveraged instead of the table-scan LEN() will cause.
you're missing the when and end
SELECT HasComments = CASE WHEN (LEN(Comments) > 1) WHEN 1 THEN 1 ELSE 0 END
FROM TableName
Since you have no WHERE clause, you're most likely returning a column of data:
SELECT CASE WHEN LEN(Comments) > 1 THEN 1 ELSE 0 END as 'HasComments'
FROM TableName
For newer SQL versions:
SELECT CASE WHEN LEN(Comments) > 1 THEN 1 ELSE 0 END FROM TableName