带有可选值的SELECT查询

时间:2015-03-27 09:41:33

标签: sql-server database tsql

我正在寻找一个简单的查询来从一个表中返回一行。

我有一个表有一个键列和一些可以为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;它是最准确的关键

5 个答案:

答案 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 34。如果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)