我在SQL Server中有一个类似于以下示例的视图。
SELECT *
FROM PEOPLE
LEFT OUTER JOIN (SELECT ID
FROM OTHER_TABLE
WHERE SOME_FIELD = 'x'
OR SOME_FIELD = 'y'
OR SOME_FIELD = 'z') AS PEOPLE_TO_EXCLUDE ON PEOPLE.ID = PEOPLE_TO_EXCLUDE.ID
WHERE PEOPLE_TO_EXCLUDE.ID IS null
麻烦:
我完全有能力添加和修改“OR SOME_FIELD ='w'”无数次。但是,我正在为用户提供此视图以通过ODBC提取excel。用户需要能够根据自己的喜好修改内部选择,以匹配她在当天/周/月/年/等的那个时间限制的任何内容。我需要以允许她轻松限制SOME_FIELD的方式进行此操作。
有没有人有关于如何实现这一目标的建议?理想情况下,我可以给她一个视图,她可以将一个逗号分隔的值列表,SOME_FIELD不能。由于人们在OTHER_TABLE中可能有多行,因此我不能仅限于该表的限制。例如,有人可能有SOME_FIELD ='x',但在表中有一行SOME_FIELD ='s'。这个人应该被排除在外,因为他们有'x',即使他们也有's'。这就是为什么内部选择是必要的。
感谢您的帮助。
答案 0 :(得分:2)
不要为EXCEL用户创建查询,他们总是打破它们,然后你必须调试它们。而是创建存储过程,传入CSV。在存储过程中,使用拆分功能拆分CSV并加入其中。用户将只有一个EXCEL查询,如:
EXEC YourProcedure 'x,y,z'
因此,他们不会破坏查询。
要帮助拆分函数,请参阅:"Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog ,然后有很多方法可以在SQL Server中拆分字符串。本文涵盖几乎所有方法的PRO和CON:
您需要创建拆分功能。这就是如何使用拆分功能:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
I prefer the number table approach to split a string in TSQL但是有很多方法可以在SQL Server中拆分字符串,请参阅上一个链接,该链接解释了每个链接的PRO和CON。
要使Numbers Table方法起作用,您需要进行一次性表设置,这将创建一个包含1到10,000行的表Numbers
:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
设置Numbers表后,创建此拆分功能:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
您现在可以轻松地将CSV字符串拆分为表格并加入其中:
Create Procedure YourProcedure
@Filter VARCHAR(1000)
AS
SELECT
p.*
FROM PEOPLE p
LEFT OUTER JOIN (SELECT
o.ID
FROM OTHER_TABLE o
INNER JOIN (SELECT
ListValue
FROM dbo.FN_ListToTable(',',@Filter )
) f ON o.SOME_FIELD=f.ListValue
) x ON p.ID=x.ID
WHERE x.ID IS null
GO