我正在寻找一个简单的查询来从一个表中返回一行。
我有一个表有一个键列和一些可以为NULL的列。该表没有以任何方式排序。
以下是一个示例表:
| KEY | ValCol1 | ValCol2 | ValCol3 |
| 1 | 123 | 222 | NULL |
| 2 | NULL | 333 | NULL |
| 3 | NULL | NULL | abc |
| 4 | NULL | NULL | NULL | <- Default-Column
| 5 | 999 | NULL | bbb |
| 6 | 123 | 444 | bbb |
对于所有可以为空的列,我现在有一个要在表中搜索的值:
搜索值:ValCol1 = 123
,ValCol2 = 444
,ValCol3 = abc
这些搜索值现在应该给我键3,因为至少第三列给了我一个匹配。
如果找不到匹配项,则查询应返回包含所有NULL值的最后一行。如果与列匹配,则查询应返回此密钥:
E.g。
搜索值:ValCol1 = 123
,ValCol2 = 444
,ValCol3 = abc
返回键6 - &gt;它是最准确的关键
答案 0 :(得分:1)
此代码会在大多数匹配后对行进行排名:
--Test data:
DECLARE @t table([KEY] int identity(1,1), ValCol1 char(3),
ValCol2 char(3), ValCol3 char(3))
INSERT @t values
('123','222',NULL),
(NULL,'333',NULL),
(NULL,NULL,'abc'),
(NULL,NULL,NULL)-- <- Default-Column
DECLARE @ValCol1 char(3)= 123
DECLARE @ValCol2 char(3)= 444
DECLARE @ValCol3 char(3)= 'abc'
--Query:
;WITH CTE AS
(
SELECT [KEY], ValCol1, ValCol2, ValCol3,
CASE WHEN ValCol1 = @ValCol1
THEN 100
WHEN ValCol1 <> @ValCol1
THEN 0
ELSE 10 END +
CASE WHEN ValCol2 = @ValCol2
THEN 100
WHEN ValCol2 <> @ValCol2
THEN 0
ELSE 10 END +
CASE WHEN ValCol3 = @ValCol3
THEN 100
WHEN ValCol3 <> @ValCol3
THEN 0
ELSE 10 END BestMatchrating
FROM @t
WHERE
ValCol1 = @ValCol1 or
ValCol2 = @ValCol2 or
ValCol3 = @ValCol3 or
(ValCol1 is null and ValCol2 is null and ValCol3 is null)
)
SELECT TOP 1 [KEY], ValCol1, ValCol2, ValCol3
FROM
CTE
ORDER BY
BestMatchrating DESC
结果:
KEY ValCol1 ValCol2 ValCol3
3 NULL NULL abc
答案 1 :(得分:0)
试试这个:
DECLARE @t TABLE ( K INT, V1 INT, V2 INT, V3 INT )
INSERT INTO @t
VALUES ( 1, 123, 222, NULL ),
( 2, NULL, 333, NULL ),
( 3, NULL, NULL, 444 ),
( 4, NULL, NULL, NULL );
WITH cte
AS ( SELECT * ,
ROW_NUMBER() OVER ( ORDER BY CASE WHEN v1 IS NULL
AND v2 IS NULL
AND v3 IS NULL
THEN 1
ELSE 0
END, K ) AS rn
FROM @t
WHERE V1 = 123
OR V2 = 444
OR V3 = 444
OR ( V1 IS NULL
AND V2 IS NULL
AND V3 IS NULL
)
)
SELECT *
FROM cte
WHERE rn = 1
输出:
K V1 V2 V3
1 123 222 NULL
答案 2 :(得分:0)
最简单的解决方案如下:
declare @valCol3 nvarchar(50) = 'abc'
declare @valCol2 nvarchar(50) = '444'
declare @valCol1 nvarchar(50) = '123'
select top 1 * from (
select *, 0 as priority
from #tmp
where [ValCol1] is null
and [ValCol2] is null
and [ValCol3] is null
union
select *, 1 as priority
from #tmp
where [ValCol3] = @valCol3
union
select *, 2 as priority
from #tmp
where [ValCol2] = @valCol2
and [ValCol3] = @valCol3
union
select *, 3 as priority
from #tmp
where [ValCol1] = @valCol1
and [ValCol2] = @valCol2
and [ValCol3] = @valCol3
) as t1
order by t1.priority desc
Init表查询:
create table #tmp (
[Key] bigint,
[ValCol1] nvarchar(50),
[ValCol2] nvarchar(50),
[ValCol3] nvarchar(50)
)
insert into #tmp values (1, '123', '222', null)
insert into #tmp values (2, null, '333', null)
insert into #tmp values (3, null, null, 'abc')
insert into #tmp values (4, null, null, null)
答案 3 :(得分:0)
请试试这个:
SELECT KEY FROM table
WHERE (ValCol1 = '123' or ValCol1 is null)
And (ValCol2 = '444' or ValCol2 is null)
And (ValCol3 = 'abc' or ValCol3 is null)
这将返回KEY 3
和4
。如果ValCol3
不是'abc'
。它应该返回4
。
答案 4 :(得分:-1)
试试这个:
SELECT top 1 max(Key)
FROM
(
SELECT "match" as "resultSet", * FROM table
WHERE
(ValCol1 = "123" OR ValCol2 = "444" OR ValCol3 = "abc")
union
SELECT "default" as "resultSet", * FROM table
WHERE
(ValCol1 IS NULL AND ValCol2 IS NULL AND ValCol3 IS NULL)
) a
Group by resultSet
order by max(Key)