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

时间:2010-11-19 17:13:41

标签: sql sql-server excel odbc

我在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'。这就是为什么内部选择是必要的。

感谢您的帮助。

1 个答案:

答案 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