2010-11-19 16 views
0

J'ai une vue dans SQL Server qui ressemble un peu à l'exemple suivant.Utilisation de Microsoft Query et ODBC vers SQL Server, requête compliquée

  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 

Les tracas:

Je suis parfaitement capable d'ajouter et de modifier "OU un_champ = 'w'" un nombre incalculable de fois. Cependant, je fais ce point de vue pour un utilisateur à extraire dans Excel via ODBC. L'utilisateur doit être capable de modifier la sélection intérieure à son gré, pour correspondre à ce qu'elle arrive à limiter à ce moment de la journée/semaine/mois/année/etc. Je dois faire ceci d'une manière qui lui permette de limiter facilement sur SOME_FIELD.

Est-ce que quelqu'un a des suggestions sur la façon d'accomplir cela? Idéalement, je pourrais lui donner une vue, qu'elle pourrait mettre une liste de valeurs séparées par des virgules que SOME_FIELD ne peut pas être. Puisque les gens peuvent avoir plusieurs lignes dans OTHER_TABLE, je ne peux pas avoir sa limite de cette table spécifiquement. Par exemple, quelqu'un peut avoir SOME_FIELD = 'x' mais aussi avoir une ligne dans la table où SOME_FIELD = 's'. Cette personne devrait être exclue parce qu'elle a «x» même si elle a aussi «s». C'est pourquoi le choix interne est nécessaire.

Merci pour votre aide.

Répondre

2

Ne créez pas de requêtes pour les utilisateurs EXCEL, ils les cassent toujours et vous devez ensuite les déboguer. Au lieu de cela, créez une procédure stockée, transmettez un fichier CSV. Dans la procédure stockée, divisez le fichier CSV à l'aide d'une fonction de division et joignez-vous à lui. L'utilisateur n'aura qu'une requête EXCEL comme:

EXEC YourProcedure 'x,y,z' 

Par conséquent, ils ne briseront pas la requête. Pour obtenir de l'aide sur la fonction fractionnée, voir: "Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog, il existe plusieurs manières de séparer une chaîne dans SQL Server. Cet article couvre les PROs et CONs de presque toutes les méthodes:

Vous devez créer une fonction de division. Voici comment une fonction split peut être utilisé:

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 mais il existe de nombreuses façons de diviser les chaînes dans SQL Server, voir le lien précédent, ce qui explique les avantages et les inconvénients de chacun.

Pour la méthode de table de nombres au travail, vous devez faire une configuration de table de temps, ce qui va créer une table Numbers qui contient des lignes de 1 à 10 000:

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) 

Une fois la table des numéros est mis en place , créez cette fonction split:

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 

Vous pouvez maintenant facilement découper une chaîne CSV dans une table et se joindre à elle:

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 
+0

Génial, merci beaucoup. – wilbbe01