使用Microsoft Query和ODBC到SQL Server,复杂的查询

我有一个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中调用这个视图。 用户需要能够根据自己的喜好来修改内部select,以匹配在当天/周/月/年/当时所限制的任何内容。 我需要这样做,让她可以轻松地限制在SOME_FIELD。

有没有人有如何做到这一点的build议? 理想情况下,我可以给她一个看法,她可以把逗号分隔的值列表,SOME_FIELD不能。 由于OTHER_TABLE中的人可能有多行,因此我不能仅限于此表。 例如,某人可能有SOME_FIELD ='x',但在SOME_FIELD ='s'的表中也有一行。 这个人应该被排除,因为他们有'x',即使他们也有''。 所以这就是为什么内部select是必要的。

谢谢你的帮助。

不要为EXCEL用户创build查询,他们总是打破他们,然后你必须debugging它们。 相反,创build一个存储过程,传递一个CSV。 在存储过程中,使用分割函数分割CSV并join。 用户将只有一个EXCEL查询,如:

 EXEC YourProcedure 'x,y,z' 

因此,他们不会中断查询。

有关分割函数的信息,请参阅Erland Sommarskog的“使用表值参数的SQL Server 2008中的数组和列表” ,然后在SQL Server中分割string的方法有很多种。 本文涵盖了几乎所有方法的PRO和CON:

你需要创build一个拆分function。 这是如何使用拆分function:

 SELECT * FROM YourTable y INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value 

我更喜欢使用数字表格的方法来在TSQL中分割一个string,但是在SQL Server中有很多方法来拆分string,参见前面的链接,它解释了每个链接的PRO和CON。

要使数字表格方法起作用,您需要执行一次性表格设置,这将创build一个包含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表设置好后,创build这个分割函数:

 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 

您现在可以轻松地将一个CSVstring拆分成一个表格并join:

 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