SQL Server case when date is null then select first then do another condition - sql-server

I have a query where I am trying to do some conditions, but I always fail one out of the 3.
1st look if dischargedate is null then set order to 1, if dischargedate is not null then look into Rank column and pick the lowest rank and order by it. Query Below
For ClientId 3634164 I have 4 entries and works(picks the lowest rank as 1 as order of sort )
For ClientId 3634514 sees I have a dischargedate as null and that is our 1 order of sort
Where I fail is on ClientID 3634795, I have a dischargedate null but still picks the lowest rank as 1. How can I make it so that it picks the dischargedate as order of sort for that one?
The issue is with my sort only on ROW_NUMBER. In photo 1 and 2 pass but 3 the sort order 3 should be 1 Query
WITH CTE AS (
SELECT PC.OP__DOCID AS LegacyClientProgramId,
PC.ClientKey AS ClientId,
PC.PgmKey AS ProgramId,
CASE WHEN Date_Discharged_Program IS NULL THEN 4 ELSE 5 END AS STATUS,
PC.Date_Admit_Program AS RequestedDate,
PC.Date_Admit_Program AS EnrolledDate,
PC.Date_Discharged_Program AS DischargedDate,
TX.RANK,
ROW_NUMBER() OVER(PARTITION BY PC.ClientKey ORDER BY case when PC.Date_Discharged_Program
IS NULL THEN 0
when TX.Rank IS NOT NULL THEN 0
ELSE 1 END, TX.Rank) AS sortOrder
FROM FD__PROGRAM_CLIENT PC
LEFT JOIN LT__TXPLANHIERARCHY TX ON PC.PgmKey = TX.PgmKey
WHERE pc.ClientKey in ( SELECT ClientKey FROM LT__MIGRATE_CLIENT)
) SELECT LegacyClientProgramId,
ClientId,
ProgramId,
STATUS,
RequestedDate,
EnrolledDate,
DischargedDate,
sortOrder,
RANK,
CASE WHEN sortOrder = 1 THEN 'Y' ELSE 'N' END AS PrimaryAssignment
FROM CTE
WHERE ProgramId <> 54

You are assigning 0 to two different cases in your ROW_NUMBER() OVER ORDER BY ...) logic. This is placing PC.Date_Discharged_Program IS NULL and TX.Rank IS NOT NULL records at an equal starting position, with only TX.Rank acting as a tiebreaker. Since multiple rows have Rank = 60, the winner (sortOrder 1) is arbitrarily chosen.
Try:
... ORDER BY case when PC.Date_Discharged_Program IS NULL THEN 0
when TX.Rank IS NOT NULL THEN 1
ELSE 2
END,
TX.Rank) AS sortOrder

Related

T-SQL grouping values on multiple columns and return row values as columns

I have a dataset which returns a number of row, 2 columns RoomType and FaultTypeName should be grouped but those 2 columns also have 1 'Result' column. Because of the 'Result' column the grouping will fail. So to make it clearer, the result set looks as follows:
The FaultTypeName are always the same three values 'Methode (M)', 'Periodiek (P)' or Vuil (V). These values should be returned as new columns with respectively their result values. So above resultset should be returned as following:
I already tried to do something with the rownumber (hence the rn column) but this didn't quite work out:
select
...
from(
select MeasurementId, RoomType, FaultTypeName, Result,
row_number() over(partition by RoomType order by RoomType, FaultTypeName) rn
from vwReportData
where measurementid = 1382596
)sub
There is a possibility that only 2 (or less) of the 3 columns (Methode, Periodiek and Vuil) are returned instead of all 3 (so less rows), if this is the case, the missing FaultTypeName(s) should still be added as column but with a result of 0.
Any ideas how I can get the right output?
Try this:
select *
from
(
select MeasurementId, RoomType, FaultTypeName, Result,
row_number() over(partition by RoomType order by RoomType, FaultTypeName) rn
from vwReportData
where measurementid = 1382596
) DS
PIVOT
(
MAX(result) for rn in ([1], [2], [3])
) PVT
In the end I figured it out myself:
SELECT
MeasurementId,
RoomType,
M = ISNULL(MIN(CASE WHEN FaultTypeName = 'Methode (M)' THEN Result ELSE NULL END), 0),
P = ISNULL(MIN(CASE WHEN FaultTypeName = 'Periodiek (P)' THEN Result ELSE NULL END), 0),
V = ISNULL(MIN(CASE WHEN FaultTypeName = 'Vuil (V)' THEN Result ELSE NULL END), 0)
FROM vwReportData
WHERE MeasurementId = 1382596
GROUP BY MeasurementId, RoomType

Count Case with 2 columns with the same values (Clarified)

Basically I want COUNT a CASE when values are present in 2 columns.
For example:
SELECT
COUNT
(CASE WHEN 1.sample AND 2.sample IN ('a','b','c')
THEN 1
ELSE NULL
END
) AS CASE
FROM table1 AS 1
INNER JOIN table2 AS 2
...
Message:
Conversion failed when converting the varchar value '08:12.06' to data
type int. Warning: Null value is eliminated by an aggregate or other
SET operation.
I get what's triggering the error, I just don't know a solution to count the case when values are present in both columns.
Can you try this and see if it works? I think this is what you are looking for.
SELECT
SUM
(CASE WHEN 1.sample IN ('a','b','c') AND 2.sample IN ('a','b','c')
THEN 1
ELSE 0
END
) AS CASE
FROM table1 AS 1
INNER JOIN table2 AS 2
You need to list the columns separately for comparison. Usually I specify a column to count, and you do not need to put NULL for the else condition.
SELECT
COUNT
(CASE WHEN 1.sample IS NULL OR 2.sample IS NULL THEN 0
WHEN ( 1.sample IN ('a','b','c')
AND 2.sample IN ('a','b','c')
)
THEN 1.sample
END
) AS CASE
FROM table1 AS 1
INNER JOIN table2 AS 2 ON....

Creating unique identifier column(1 or zero) Rank () SQL SERVER

I am trying to create a column in SQL SERVER that shows 1 OR 0(zero). I have a column of customer numbers that appear more than once. At the first hit on a unique non-repeated customer number it should show one and if it is repeated then 0(zero). How can I create this ?
CustNumber Unique
25122134 1
25122134 0
25122134 0
25122136 1
25122136 0
the solutions I am considering and trying out now are Rank() and Rank_DENSE().
declare #test table
(
CustNumber int
)
insert into #test values
(25122134),
(25122134),
(25122134),
(25122136),
(25122136)
select
* ,
// each CustNumber in partition has the same rank, but different row_number
case when (row_number() over (partition by CustNumber order by CustNumber)) = 1
then 1 else 0 end as [Unique]
// the 1st is unique, the rest (2..n) are not
from #test
order by CustNumber, [Unique] desc
// unique in each group should be displayed first
You don't want RANK because that, by definition, produces the same output for identical inputs.
ROW_NUMBER() and a simple CASE expression should do it:
;WITH Numbered as (
SELECT CustNumber,
ROW_NUMBER() OVER (PARTITION BY CustNumber
ORDER BY CustNumber) as rn --Unusual - pick a real column if you have a preference
FROM YourUnnamedTable
)
SELECT CustNumber,CASE WHEN rn = 1 THEN 1 ELSE 0 END as [Unique]
FROM Numbered

How to count the number of rows with specific data in mssql

I have the following table:
Items:
ID Type StockExists
01 Cellphone T
02 Cellphone F
03 Apparrel T
I want to count the number of items with existing stocks, i.e., the number of rows with StockExists='T'. I was performing the query as;
Select count(StockExists)
From [Items] where StockExists='T'
but it is always returning 1. What is the right way to do it?
Edit:
Also, how to perform another such Count operation and add them together in one row, for example,
Select count(StockExists)
From [Items] where StockExists='T'` and `Select count(Type)
From [Items] where Type='Cellphone'` ?
SELECT
COUNT(*) As ExistCount
FROM
dbo.Items
WHERE
StockExists='T'
So your query should work.
Result:
EXISTCOUNT
2
Demo
Update
How to perform another such Count operation and add them together in
one row, for example, Select count(StockExists) From [Items] where
StockExists='T' and Select count(Type) From [Items] where
Type='Cellphone' ?
You can use SUM with CASE:
SELECT
ExistCount = SUM(CASE WHEN StockExists='T' THEN 1 ELSE 0 END) ,
CellphoneCount = SUM(CASE WHEN Type='Cellphone' THEN 1 ELSE 0 END)
FROM
dbo.Items
Result:
EXISTCOUNT CELLPHONECOUNT
2 2
Demo
Select Sum(Case when field = 'this' then 1 else 0 end) as Total
from YourTable
When using CASE WHEN better to use NULL than 0 in ELSE case like below
SELECT
ExistCount = SUM(CASE WHEN StockExists='T' THEN 1 ELSE NULL END) ,
TotalCount = COUNT(ID)
FROM
dbo.Items

If any clause when grouping

Doing a Sum() on a column adds up the values in that column based on group by. But lets say I want to sum these values only if all the values are not null or not 0, then I need a clause which checks if any of the values is 0 before it does the sum. How can I implement such a clause?
I'm using sql server 2005.
Thanks,
Barry
Let's supose your table schema is:
myTable( id, colA, value)
Then, one approach is:
Select colA, sum(value)
from myTable
group by colA
having count( id ) = count( nullif( value, 0 ))
Notice that nullif is a MSSQL server function. YOu should adapt code to your rdbms brand.
Explanation:
count aggregate function only count not null values. Here a counting null values test.
You say that 0+2+3=0 for this case. Assuming that NULL+2+3 should also be zero:
SELECT GroupField,
SUM(Value) * MIN(CASE WHEN COALESCE(Value, 0) = 0 THEN 0 ELSE 1 END)
FROM SumNonZero
GROUP BY GroupField
The above statement gives this result
GroupField (No column name)
case1 5
case2 0
case3 0
with this test data
CREATE TABLE SumNonZero (
GroupField CHAR(5) NOT NULL,
Value INT
)
INSERT INTO SumNonZero(GroupField, Value)
SELECT 'case1', 2
UNION ALL SELECT 'case1', 3
UNION ALL SELECT 'case2', 0
UNION ALL SELECT 'case2', 2
UNION ALL SELECT 'case2', 3
UNION ALL SELECT 'case3', NULL
UNION ALL SELECT 'case3', 3
UNION ALL SELECT 'case3', 4
It makes no sense to eliminate 0 from a SUM because it wont impact the sum.
But you may want to SUM based on another field:
select FIELD, sum(
case when(OTHER_FIELD>0) then FIELD
else 0
end)
from TABLE
group by TABLE

Resources