Sql 存储过程:通过匹配输入参数选择或返回空记录

Sql 存储过程:通过匹配输入参数选择或返回空记录,sql,sql-server,database,tsql,stored-procedures,Sql,Sql Server,Database,Tsql,Stored Procedures,我有以下情况: 有一张这样的桌子: Id | Param | Value ------ | ------ | ------------- 1 | 1 | One 1 1 | NULL | Null-Value 1 1 | 2 | Two 1 1 | 3 | Three 3 2 | NULL | Nul-Value 2 2 | 2 | Two 2 3 | NULL |

我有以下情况:

有一张这样的桌子:

Id     | Param  | Value
------ | ------ | -------------
1      | 1      | One 1
1      | NULL   | Null-Value 1
1      | 2      | Two 1
1      | 3      | Three 3
2      | NULL   | Nul-Value 2
2      | 2      | Two 2
3      | NULL   | Null-Value 3
4      | 1      | One 4
5      | NULL   | Null-Vaue  5
6      | NULL   | Null-Value 6
我必须为Param编写一个存储过程,作为给定的输入nullable参数。我必须生成一个结果,该结果将包含一个具有ID和值的表,并且结果基于以下逻辑-

如果输入参数为null-返回参数值为null的所有行


如果参数不为null,则在Param列中返回与该参数匹配的行,以及其他ID的所有行,这些ID的值为null作为Param

每个Id只能有一个结果

考虑在Id和Param列上应用了唯一的复合索引

例如:

示例2让我也包括Param列以获得更好的可见性:

我想这将是一个表与自身的连接,或者更好地使用crossor或outer apply和一些适当的where子句。。。
您可以在不使用连接的情况下使用这个。当@param为null时,它返回所有行

DECLARE @t TABLE (id INT, [Param] INT, Val VARCHAR(50))
INSERT INTO @t VALUES
(1, 1,' One 1'),
(1, NULL,'Null-Value 1'),
(1, 2,'Two 1'),
(1, 3,'Three 3'),
(2,NULL,'Nul-Value 2'),
(2, 2,'One 2'),
(3, NULL,'Null-Value 3'),
(4, 1,'One 4'),
(5, NULL,'Null-Vaue 5'),
(6, NULL,'Null-Value 6')

DECLARE @Param INT
SET @Param = 1

SELECT *
FROM @t
WHERE @Param IS NULL OR (([Param] = @Param) OR ([Param] IS NULL AND Id <> @Param))

这解决了每个id有多个结果的问题。您没有为每个id提供任何规则,因此我无法执行下一步

SELECT *
FROM tableyoudidnotsaythenameof as x
WHERE (coalesce(x.value, @inparam) = @inparam) or
      (@inparam is null and x.value is null)
如果您不在乎在每个id有多个id时返回哪一个id,这将起作用:

SELECT * 
FROM (
  SELECT *, row_number() over (partition by id) as rn
  FROM tableyoudidnotsaythenameof as x
  WHERE (coalesce(x.value, @inparam) = @inparam) or
        (@inparam is null and x.value is null)
) zed
WHERE zed.rn = 1
要使用较大的rn对空值进行排序,请执行以下操作:

  SELECT *, row_number() over (partition by id order by CASE WHEN x.value is null then 2 else 1 END) as rn

我想出来了。以下是查询:

declare @input int = 2

select t.Id, t.Value
from [dbo].[MyTable] t
outer apply (select * from MyTable t2
             where t2.Param = @input
             and t.Id = t2.Id) mt
where  (t.Id = mt.Id and t.Param = @input)
or (t.Param is null and mt.Param is null)

到目前为止你写了什么?您得到了什么错误?类似于这样的错误:从[dbo].[MyTable]中选择t.Id、t.MyParam、t.MyValuet outer apply select*从MyTable t2中选择,其中t2.MyParam=@input和t.Id=t2.Id和t.MyParam=t2.MyParam mt,其中mt.MyParam=@input和t.MyParam不为null或t.MyParam为null,但它也返回Id 1的null值,其余的值为ok。outer apply使我哭泣。我们没有在标题中列出解决的问题。特别是当所选答案如此糟糕时。如果@Param为null,则只返回所有行。每个id应该只有一个结果,因为id和Param上应用了唯一的索引,因此它将与null作为Pram或与输入参数匹配。上述示例不适用于不同于1和1的输入参数null@peev-当然会的。你试过了吗?是的,我只是用我的替换了表名,而不是x.value-x.param,我在分区中按id放置了一个order by id,因为它是必需的。@peev-这是一个谜,你期望2的输出是什么,这与你得到的有什么不同?返回Param列中与该参数匹配的行,以及所有作为Param具有null值的行-返回带有行的表,具有Param=@inparam的和具有Param=null的。见上文,我已经更新了问题帖子
  SELECT *, row_number() over (partition by id order by CASE WHEN x.value is null then 2 else 1 END) as rn
declare @input int = 2

select t.Id, t.Value
from [dbo].[MyTable] t
outer apply (select * from MyTable t2
             where t2.Param = @input
             and t.Id = t2.Id) mt
where  (t.Id = mt.Id and t.Param = @input)
or (t.Param is null and mt.Param is null)