I have a table that looks like this:
CREATE TABLE [Test].[dbo].[MyTest]
(
[Id] INT NOT NULL,
[ColA] VARCHAR(255) NULL,
[ColB] VARCHAR(255) NULL,
[ColC] VARCHAR(255) NULL,
[ColD] VARCHAR(255) NULL
);
And let’s say I have:
Id ColA ColB ColC ColD
---------------------------------------
1 A B NULL C
2 A A NULL D
3 NULL A B NULL
4 B B B B
5 NULL NULL NULL NULL
What I’m trying to do is select every row from this table, but only want the first 2 distinct non-null values from ColA-ColD, in order. In other words, If for one row ColA & ColB are both non-null and are distinct from each other, those are the 2 that I want for that row. Using the data I gave above, the wanted results from this query would be:
1, A (from ColA), B (from ColB)
2, A (from ColA), D (from ColD)
3, A (from ColB), B (from ColC)
4, B (from ColA)
Notice that if all data for ColA-D for a row is NULL that row is not selected. Also it’s ok if there is only 1 non-null distinct column (you can see from result row with Id 4) – it doesn’t have to be 2, but ideally it would be 2.
Basically I would ideally be able to get the TOP(2) DISTINCT from ColA-ColD WHERE none of those are NULL, but I realize TOP and DISTINCT work on rows, not on columns like I’m trying to do. Any help greatly appreciated.
Thanks!
This might be fastest with a CTE and a
CASEstatement:The first column returned (
col1) is the first non-null column and the second column (col2) is the second distinct non-null value in that order. TheCASEstatement works, becauseNULL <> valuenever evaluates toTRUE.If there is only one distinct value,
col2returnsNULL.If all source columns are
NULL,col1isNULLand the row is filtered by theWHEREclause.The commented alternative syntax with
NULLIF()is shorter, but I don’t expect it to be faster.