我需要编写一个从表中获取一组信息的查询,但如果没有该特定客户端的信息,则使用默认集。我想知道是否有办法避免if(exists())语句中的查询重复。
例如:
IF( EXISTS( SELECT * FROM UserTable WHERE Name = @UserName))
BEGIN
SELECT * FROM UserTable WHERE Name = @UserName))
END
ELSE
BEGIN
SELECT * FROM UserTable WHERE Name = 'Jon Skeet'))
END
前两个选择(存在和if的真实部分)完全相同。如果语句为true,我想避免两次运行相同的查询。我知道一旦满足第一个真实条件就存在停止,但这仍然是O(n)最坏的情况。
我知道的另一个选项是将信息放在临时表中,检查信息是否存在,如果没有返回默认信息。
两种方式都可以,但最好的方法是什么?还有其他方法吗?有没有办法在WHERE子句中执行此操作,因为这是唯一不同的东西?
编辑:修复了返回行而不仅仅是单个项目的示例。因此,将select转储到单个变量的答案将等于我假设的临时表。另外,不要愤怒Jon Skeet,拼错他的名字
答案 0 :(得分:6)
你可以这样做:
SELECT TOP 1
UserID
FROM
UserTable
WHERE
Name IN (@UserName, 'John Skeet')
ORDER BY
CASE WHEN Name = 'John Skeet' THEN 2 ELSE 1 END
(或使用LIMIT或任何方法用于您的RDBMS)
或者你可以这样做:
DECLARE @UserID INT
SELECT
@UserID = UserID
FROM
UserTable
WHERE
Name = @UserName
IF (@UserID IS NULL)
SELECT
@UserID = UserID
FROM
UserTable
WHERE
Name = 'John Skeet'
SELECT @UserID AS UserID
或者这个:
SELECT
COALESCE(T2.UserID, T1.UserID)
FROM
UserTable T1
LEFT OUTER JOIN UserTable T2 ON
T2.Name = @UserName
WHERE
T1.Name = 'John Skeet'
或者这个:
SELECT
UserID
FROM
UserTable
WHERE
Name = @UserName
IF (@@ROWCOUNT = 0) -- MS SQL Server specific, your RDBMS method will vary
SELECT
UserID
FROM
UserTable
WHERE
Name = 'John Skeet'
答案 1 :(得分:3)
怎么样:
DECLARE @UserID int;
SELECT @UserID = UserID FROM UserTable WHERE Name = @UserName
IF(@UserID IS NULL)
BEGIN
SELECT @UserID=UserID FROM UserTable WHERE Name = 'Jon Skeet'))
END
SELECT @UserID
答案 2 :(得分:1)
如果变量返回,您可以选择变量检查变量null运行get default query
类似的东西:
Declare @uID int;
SELECT @uID = UserID FROM UserTable WHERE Name = @UserName
IF (@uID is null)
begin
'Select default here'
End
select @uID
答案 3 :(得分:1)
如果您担心性能问题,我认为您可能不需要 - 大多数DBMS应该优化复制。如果您仍然关注性能,请同时运行它以查看您的DBMS是否存在任何问题。
如果您担心代码 - 重复代码部分的可维护性,可读性等,那么请记住上述答案。您可能会发现重复是最差的选择。令人遗憾的是SQL不具备可塑性。
答案 4 :(得分:0)
你没有说你正在使用什么DBMS,但显然不是Oracle(我知道的那个)。但是,我希望您的DBMS允许您执行类似此伪代码的操作:
SELECT UserID FROM UserTable WHERE Name = @UserName
IF <no data returned by that>
BEGIN
SELECT UserID FROM UserTable WHERE Name = 'John Skeet'
END
在Oracle中,这将是:
BEGIN
SELECT UserID INTO v_UserID FROM UserTable WHERE Name = :UserName;
EXCEPTION
WHEN NO_DATA_FOUND THEN
SELECT UserID INTO v_UserID FROM UserTable WHERE Name = 'John Skeet';
END
答案 5 :(得分:0)
除非你要为你要返回的每个字段定义一组变量(并且它只有一条记录),我认为最有效的方法是进行两次调用。临时表可能会花费更多。