单个SQL语句来选择行,但仅当恰好有一个匹配行时

单个SQL语句来选择行,但仅当恰好有一个匹配行时,sql,sql-server,Sql,Sql Server,考虑以下SQL: SELECT @Count = COUNT(*) FROM Widgets WHERE WidgetName = 'foo' IF ( @Count = 1 ) BEGIN SELECT @WidgetId = WidgetId FROM Widgets WHERE WidgetName = 'foo' END 它有效地设置@WidgetId值,但前提是只有一个匹配行满足查询。上面的查询是微不足道的,但是考虑WHERE子句相当昂贵的情况。或者如果WH

考虑以下SQL:

SELECT @Count = COUNT(*)
FROM Widgets
WHERE WidgetName = 'foo'

IF ( @Count = 1 ) BEGIN
    SELECT @WidgetId = WidgetId
    FROM Widgets
    WHERE WidgetName = 'foo'
END

它有效地设置@WidgetId值,但前提是只有一个匹配行满足查询。上面的查询是微不足道的,但是考虑WHERE子句相当昂贵的情况。或者如果WHERE子句比单个完整列更复杂。在WidgetName(如“%foo%”)中,有没有一种方法可以执行单个查询以将值分配给参数,但只能在恰好有一行匹配时执行,而无需重复WHERE子句?

这将起作用,并且不需要您执行多个SELECT语句。如果需要的话,您将有很大的自由更改查询,而不会破坏任何内容


这将起作用,并且不需要您执行多个SELECT语句。如果需要的话,您将有很大的自由更改查询,而不会破坏任何内容


如果我理解正确,您可以使用HAVING子句仅在计数等于1时成功设置@WidgetId变量。像这样的方法应该会奏效:

SELECT @WidgetId = MAX(WidgetId)
FROM Widgets
WHERE WidgetName = 'Widget Name'
GROUP BY WidgetName
HAVING COUNT(*) = 1
在上述情况下,如果按WidgetName分组后只有一条记录的计数,@WidgetId将设置为MAXWidgetId


我创建了一个fiddle,您可以在这里查看:

如果我理解正确,您可以使用HAVING子句成功地仅在COUNT等于1时设置@WidgetId变量。像这样的方法应该会奏效:

SELECT @WidgetId = MAX(WidgetId)
FROM Widgets
WHERE WidgetName = 'Widget Name'
GROUP BY WidgetName
HAVING COUNT(*) = 1
在上述情况下,如果按WidgetName分组后只有一条记录的计数,@WidgetId将设置为MAXWidgetId


我已经创建了一个提琴,你可以在这里看到:

我自己会使用一组版本,并且正准备发布相同的版本。好主意!我可能把问题中最简单的例子说得太简单了。我正在寻找一种在查询比完整列值更复杂时也能工作的解决方案。我已更新问题以反映这一点。但是在这种特殊情况下,这是一个很好的解决方案。分组方法仍然可以处理更复杂的where子句和连接。精确匹配特定数量的行是一种很好的方法。是的,但它要求WHERE子句中的每个字段都是组的一部分。这可能会使查询很难阅读并在以后维护。例如,想想WHERE-IN或函数调用……我认为当WHERE子句没有选择精确的值时,它会崩溃,例如WidgetName,比如“%foo%”或WidgetDtm>@SomeDate。除非你做了那些子句CASE语句,解析出要分组的确切值,但是你基本上是在重复逻辑。我自己会使用一个分组版本,并且正要发布相同的。好主意!我可能把问题中最简单的例子说得太简单了。我正在寻找一种在查询比完整列值更复杂时也能工作的解决方案。我已更新问题以反映这一点。但是在这种特殊情况下,这是一个很好的解决方案。分组方法仍然可以处理更复杂的where子句和连接。精确匹配特定数量的行是一种很好的方法。是的,但它要求WHERE子句中的每个字段都是组的一部分。这可能会使查询很难阅读并在以后维护。例如,想想WHERE-IN或函数调用……我认为当WHERE子句没有选择精确的值时,它会崩溃,例如WidgetName,比如“%foo%”或WidgetDtm>@SomeDate。除非你做了那些子句CASE语句,解析出要分组的确切值,但是你基本上是在重复逻辑。当然谢谢此外,不严格要求使用SET NOCOUNT OFF语句;从中,即使启用了SET-NOCOUNT,@@ROWCOUNT函数也会更新。当然谢谢此外,不严格要求使用SET NOCOUNT OFF语句;从中,即使启用了SET-NOCOUNT,@@ROWCOUNT函数也会更新。