我有一个看起来像这样的表:
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
);
让我说我有:
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
我要做的是从该表中选择每一行,但只想按顺序从ColA-ColD中获取前两个不同的非空值。换句话说,如果是一行ColA& ColB都是非null并且彼此不同,那些是我想要的那一行。使用我上面给出的数据,此查询所需的结果将是:
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)
请注意,如果一行的ColA-D的所有数据都为NULL,则表示未选择该行。如果只有一个非空的不同列(你可以从结果行看到Id 4)也没关系 - 它不一定是2,但理想情况下它应该是2。
基本上我理想情况下能够从ColA-ColD获得TOP(2)DISTINCT WHERE这些都不是NULL,但我意识到TOP和DISTINCT在行上工作,而不是像我想要的那样在列上工作。非常感谢任何帮助。
谢谢!
答案 0 :(得分:2)
对于CTE和CASE
语句,这可能是最快的:
;WITH cte AS (
SELECT id
,COALESCE(ColA, ColB, ColC, ColD) AS col1
,ColB
,ColC
,ColD
FROM tbl
)
SELECT id
,col1
,CASE WHEN ColB <> col1 THEN ColB
WHEN ColC <> col1 THEN ColC
WHEN ColD <> col1 THEN ColD
ELSE NULL
END AS col2
-- ,COALESCE(NULLIF(ColB, col1)
-- ,NULLIF(ColC, col1)
-- ,NULLIF(ColD, col1)) As col2 -- alt. syntax doing the same
FROM cte
WHERE col1 IS NOT NULL
ORDER BY id
返回的第一列(col1
)是第一个非空列,第二列(col2
)是该顺序中的第二个不同的非空值。 CASE
语句有效,因为NULL <> value
永远不会评估为TRUE
。
如果只有一个不同的值,col2
会返回NULL
如果所有源列均为NULL
,则col1
为NULL
,并且该行将按WHERE
子句进行过滤。
NULLIF()
的注释替代语法较短,但我不希望它更快。
答案 1 :(得分:0)
您的数据库设计看起来不对。
可能您不应该有ColA,..,ColD
列。看起来您应该有第二个表格,其中包含id
,type
(A,..,D)和value
。
使用该结构,您可以轻松地获得任何输出。
答案 2 :(得分:0)
尝试:
select id,
coalesce(ColA, ColB, ColC, ColD) Result1,
coalesce(nullif(coalesce(ColB, ColC, ColD), coalesce(ColA, ColB, ColC, ColD)),
nullif(coalesce(ColC, ColD), coalesce(ColB, ColC, ColD)),
nullif(ColD, coalesce(ColC, ColD)) ) Result2
from [Test].[dbo].[MyTest]