IF EXISTS 在 WHERE 子句中
Posted
技术标签:
【中文标题】IF EXISTS 在 WHERE 子句中【英文标题】:IF EXISTS in WHERE clause 【发布时间】:2013-03-30 20:48:05 【问题描述】:这几天我遇到了一个问题。在我的 MS SQL 数据库中,我有一个文章表(它们的详细信息,如插入日期、插入用户和其他人员)和一个包含多种语言文章正文的表。我希望文章正文使用用户首选语言。但并非所有文章都使用所有语言。因此,最好先搜索用户首选语言的文章,如果不存在,则以第一语言获取正文。
为此,我使用了一个函数。 WHERE 子句是这样的:
WHERE [tblBody].[Language] = @Language AND
[tblTitle].[Language] = @Language
但如果是这样就好了: SELECT(如果正文是我喜欢的语言,请获取该正文;否则给我一个(也许我理解它))
我希望你明白我想做什么,女巫是我的问题。
提前谢谢你!
更新
这是我需要修改的实际查询:
ALTER FUNCTION [fx_GetNews]
(
@MinimumPermission INT,
@UserID UNIQUEIDENTIFIER,
@OwnerID UNIQUEIDENTIFIER = NULL,
@Title NVARCHAR(250) = NULL,
@Body VARCHAR(150) = NULL,
@InsertDateStart DATETIME = NULL,
@InsertDateEnd DATETIME = NULL,
@CreatedByUserID UNIQUEIDENTIFIER = NULL,
@ExpirationDate DATETIME = NULL,
@Language VARCHAR(150)
)
RETURNS @News TABLE
(
[Id] UNIQUEIDENTIFIER
,[OwnerID] UNIQUEIDENTIFIER
,[Title] NVARCHAR(250)
,[TitlePictureUrl] VARCHAR(150)
,[Body] NVARCHAR(max)
,[Visible] BIT
,[InsertDate] DATETIME
,[CreatedByUserId] UNIQUEIDENTIFIER
,[ModifiedDate] DATETIME
,[ModifiedByUserId] UNIQUEIDENTIFIER
,[ModifiedByPerson] VARCHAR(250)
,[ExpirationDate] DATETIME
,[CreatedByPerson] VARCHAR(250)
,[Permission] INT
)
AS
BEGIN
INSERT INTO @News
([Id]
,[OwnerID]
,[Title]
,[TitlePictureUrl]
,[Body]
,[Visible]
,[InsertDate]
,[CreatedByUserId]
,[ModifiedDate]
,[ModifiedByUserId]
,[CreatedByPerson]
,[ModifiedByPerson]
,[ExpirationDate]
,[Permission])
SELECT
[dbo].[tblNews].[Id]
,[dbo].[tblNews].[OwnerID]
,CAST([tblTitle].[Text] AS VARCHAR(150))
,[dbo].[tblNews].[TitlePictureUrl]
,[tblBody].[Text]
,[dbo].[tblNews].[Visible]
,[dbo].[tblNews].[InsertDate]
,[dbo].[tblNews].[CreatedByUserId]
,[dbo].[tblNews].[ModifiedDate]
,[dbo].[tblNews].[ModifiedByUserId]
,[dbo].[tblNews].[CreatedByPerson]
,[dbo].[tblNews].[ModifiedByPerson]
,[dbo].[tblNews].[ExpirationDate]
,[eportofolii].[fx_GetPermissionForObject] (@UserID, [dbo].[tblNews].[ID], 1, 1)
FROM [dbo].[tblNews]
INNER JOIN [dbo].[tblAdmTranslateText] AS [tblBody] ON
[tblBody].[OwnerID] = [dbo].[tblNews].[ID]
INNER JOIN [dbo].[tblAdmTranslateText] AS [tblTitle] ON
[tblTitle].[OwnerID] = [dbo].[tblNews].[ID]
WHERE
[eportofolii].[fx_GetPermissionForObject] (@UserID, [dbo].[tblNews].[ID], 1, 1) >= @MinimumPermission AND
([dbo].[tblNews].[OwnerID] = ISNULL(@OwnerID, [dbo].[tblNews].[OwnerID]) OR [dbo].[tblNews].[OwnerID] IS NULL) AND
[tblTitle].[Text] LIKE '%' + ISNULL(@Title, '') + '%' AND
[tblBody].[Text] LIKE '%' + ISNULL(@Body, '') + '%' AND
([dbo].[tblNews].[InsertDate] BETWEEN ISNULL(@InsertDateStart, ([dbo].[tblNews].[InsertDate] - 7)) AND ISNULL(@InsertDateEnd, [dbo].[tblNews].[InsertDate] + 1)) AND
[dbo].[tblNews].[CreatedByUserID] = ISNULL(@CreatedByUserID, [dbo].[tblNews].[CreatedByUserID]) AND
([dbo].[tblNews].[ExpirationDate] > ISNULL(@ExpirationDate, GETDATE() - 1) OR [dbo].[tblNews].[ExpirationDate] IS NULL) AND
[tblBody].[UDF_2] = 'Body' AND
[tblTitle].[UDF_2] = 'Title' AND
[tblBody].[UDF_1] = 'News' AND
[tblTitle].[UDF_1] = 'News' AND
[tblBody].[Language] = @Language AND
[tblTitle].[Language] = @Language
ORDER BY [InsertDate] DESC
RETURN
END
问题在最后:
[tblBody].[Language] = @Language AND
[tblTitle].[Language] = @Language
谢谢!
【问题讨论】:
还给你哪一个?请问是哪个版本的SQL Server? 您是否真的将文章的正文和标题存储在单独的表格中?是否有第三张表用于发布日期,第四张用于作者 ID 等?如果你展示你的实际表结构以及它们之间的关系,你可能会得到有效的查询而不是猜测...... 有一个新闻详细信息表(出版日期、作者...)和另一个包含不同语言文本的表格。第二个表包括不同行的标题和正文。 【参考方案1】:;WITH x AS
(
SELECT b.[Language], /* other columns from b */
rn = ROW_NUMBER() OVER (PARTITION BY b.article_id_of_some_kind
ORDER BY CASE WHEN t.[Language] = @Language THEN 1 ELSE 2 END)
FROM dbo.tblBody AS b
INNER JOIN dbo.tblLanguage AS l
ON b.LanguageID = l.LanguageID -- guessing here
)
SELECT /* cols */ FROM x WHERE rn = 1;
如果首选语言不可用,这将返回任意语言。您可以通过修改内部 ORDER BY
来进一步细化它。
【讨论】:
【参考方案2】:你想做的有点复杂。您希望以所需语言(如果存在)返回文章,如果不存在,则以另一种语言返回。
为此,窗口函数非常有用:
select t.*
from (select blah,
max(case when [tblBody].[Language] = @Language then 1 else 0 end) over (partition by article) as HasLanguage
from whatever
where [tblTitle].[Language] = @Language
) t
where HasLanguage = 1 or [tblBody].[Language] <> @Language
【讨论】:
【参考方案3】:select B.*
from bodies as B
where exists (
select 1 from (
select b.article, coalesce( u.language, b.language ) as language
from bodies as b
left join users as u
on b.language = u.language
and u.user = @user
where b.article = @article
and b.default_language = 'TRUE' -- or whatever
) as A
on A.article = B.Article
and A.language = B.language
)
您必须在两种语言之间进行选择:用户语言和文章语言。您可以使用UNION
或coalesce
(因为外连接是一种联合),后者更简单。
【讨论】:
【参考方案4】:一种选择是使用 MSSQL "COALESCE" 函数:
http://msdn.microsoft.com/en-us/library/ms190349.aspx另一个可能是使用 CASE 块。
【讨论】:
以上是关于IF EXISTS 在 WHERE 子句中的主要内容,如果未能解决你的问题,请参考以下文章
Linq to Entities 添加 Where 子句以在另一个表中查找 EXISTS
通过 FETCH NEXT 子句加速 WHERE EXISTS 子句
Oracle where exists 子句不适用于 SQL Plus
sql面试题_SQl优化技巧_1注意通配符中like的使用,百分号放后面_2避免在where子句中对字段进行函数操作_3在子查询当中,尽量用exists代替in_4where子句中尽量不要使用(代码片