Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Conditional Case

I have a table that lists items and a status about these items. The problem is that some items have multiple different status entries. For example.

HOST          Status
1.1.1.1       PASS
1.1.1.1       FAIL
1.2.2.2       FAIL
1.2.3.3       PASS
1.4.2.1       FAIL
1.4.2.1       FAIL
1.1.4.4       NULL

I need to return one status per asset.

HOST          Status
1.1.1.1       PASS
1.2.2.2       FAIL
1.2.3.3       PASS
1.4.2.1       FAIL
1.1.4.4         No Results

I have been trying to do this with T-SQL Case statements but can't quite get it right. The conditions are any Pass + anything is a Pass, Fail+ No Results is a fail and Null is No Results.

like image 973
Eddie D Avatar asked Jan 06 '14 20:01

Eddie D


People also ask

How does Case condition work in SQL?

The SQL CASE ExpressionThe CASE expression goes through conditions and returns a value when the first condition is met (like an if-then-else statement). So, once a condition is true, it will stop reading and return the result. If no conditions are true, it returns the value in the ELSE clause.

Can we put case in WHERE condition in SQL?

The CASE statement returns the value based on condition. We can use a case statement in Where, Order by and Group by clause.

How do I do an IF THEN statement in SQL?

Syntax. IF (a <= 20) THEN c:= c+1; END IF; If the Boolean expression condition evaluates to true, then the block of code inside the if statement will be executed. If the Boolean expression evaluates to false, then the first set of code after the end of the if statement (after the closing end if) will be executed.


2 Answers

Try using a case statement to convert to ordered results and group on that, finally, you'll need to convert back to the nice, human-readable answer:

with cte1 as (
  SELECT HOST,
         [statNum] = case
                      when Status like 'PASS' then 2
                      when Status like 'FAIL' then 1
                      else 0
                    end
  FROM table
)
SELECT HOST, case max(statNum) when 2 then 'PASS' when 1 then 'FAIL' else 'No Results' end
FROM cte1
GROUP BY HOST

NOTE: I used a CTE statement to hopefully make things a little clearer, but everything could be done in a single SELECT, like so:

SELECT HOST,
 [Status] = case max(case when Status like 'PASS' then 2 when Status like 'FAIL' then 1 else 0 end)
    when 2 then 'PASS'
    when 1 then 'FAIL'
    else 'No Result'
   end
FROM table
like image 132
chezy525 Avatar answered Oct 06 '22 23:10

chezy525


You can use Max(Status) with Group by Host to get Distinct values:

Select host, coalesce(Max(status),'No results') status
From Table1
Group by host
Order by host

Fiddle Demo Results:

|    HOST |     STATUS |
|---------|------------|
| 1.1.1.1 |       PASS |
| 1.1.4.4 | No results |
| 1.2.2.2 |       FAIL |
| 1.2.3.3 |       PASS |
| 1.4.2.1 |       FAIL |

By default SQL Server is case insensitive, If case sensitivity is a concern for your server, then use the lower() function as below:

Select host, coalesce(Max(Lower(status)),'No results') status
From Table1
Group by host
Order by host

Fiddle demo

like image 39
Kaf Avatar answered Oct 07 '22 00:10

Kaf