Question

Je dois filtrer les ensembles de résultats du serveur SQL en fonction des sélections effectuées dans une zone de liste à sélection multiple. J'ai déjà eu l'idée de créer un instrument pour déterminer si la valeur de la ligne existe dans les valeurs de filtre sélectionnées, mais cela risque de donner lieu à des correspondances partielles (par exemple, Car Match Carpet).

J'ai également scié la chaîne en une table et joint / mis en correspondance en fonction de cela, mais j'ai des réserves quant à la manière dont cela va se dérouler.

Etant donné qu'il s'agit d'une tâche apparemment courante, je me tourne vers la communauté Stack Overflow pour obtenir ses commentaires et peut-être quelques suggestions sur l'approche la plus couramment utilisée pour résoudre ce problème.

Était-ce utile?

La solution

J'ai résolu ce problème en écrivant une fonction table (nous utilisons 2005) qui prend une chaîne délimitée et retourne une table. Vous pouvez ensuite vous y joindre ou utiliser WHERE EXISTS ou WHERE x IN. Nous n'avons pas encore effectué de tests de résistance complets, mais avec une utilisation limitée et des ensembles d'éléments relativement petits, je pense que les performances devraient être correctes.

Vous trouverez ci-dessous l’une des fonctions. J'en ai aussi une écrite pour accepter spécifiquement une liste délimitée d'INT pour les valeurs d'ID dans les tables de consultation, etc.

Une autre possibilité consiste à utiliser LIKE avec les délimiteurs pour vous assurer que les correspondances partielles sont ignorées, mais que vous ne pouvez pas utiliser d'index avec cela, les performances seront donc médiocres pour toute table volumineuse. Par exemple:

SELECT
     my_column
FROM
     My_Table
WHERE
     @my_string LIKE '%|' + my_column + '|%'

.

/*
    Name:       GetTableFromStringList
    Description:    Returns a table of values extracted from a delimited list
    Parameters:
            @StringList - A delimited list of strings
            @Delimiter - The delimiter used in the delimited list

    History:
    Date        Name            Comments
    ----------  -------------   ----------------------------------------------------
    2008-12-03  T. Hummel   Initial Creation
*/
CREATE FUNCTION dbo.GetTableFromStringList
(
    @StringList VARCHAR(1000),
    @Delimiter  CHAR(1) = ','
)
RETURNS @Results TABLE
(
    String  VARCHAR(1000)   NOT NULL
)
AS
BEGIN
    DECLARE
        @string     VARCHAR(1000),
        @position   SMALLINT

    SET @StringList = LTRIM(RTRIM(@StringList)) + @Delimiter
    SET @position = CHARINDEX(@Delimiter, @StringList)

    WHILE (@position > 0)
    BEGIN
        SET @string = LTRIM(RTRIM(LEFT(@StringList, @position - 1)))

        IF (@string <> '')
        BEGIN
            INSERT INTO @Results (String) VALUES (@string)
        END

        SET @StringList = RIGHT(@StringList, LEN(@StringList) - @position)
        SET @position = CHARINDEX(@Delimiter, @StringList, 1)
    END

    RETURN
END

Autres conseils

  

J'ai eu l'idée de faire un   instring pour déterminer si la valeur de la ligne   existe dans les valeurs de filtre sélectionnées,   mais c'est sujette à des allumettes partielles   (par exemple, allumettes de voiture moquette)

Il me semble que vous n'incluez pas d'ID unique, ni éventuellement de clé primaire dans les valeurs de votre zone de liste. Idéalement, chaque option aura un identifiant unique qui correspond à une colonne de la table sur laquelle vous recherchez. Si votre zone de liste était comme ci-dessous, vous pourrez alors filtrer spécifiquement pour les voitures car vous obtiendrez la valeur unique 3.

<option value="3">Car</option>
<option value="4">Carpret</option>

Ensuite, vous créez simplement une clause where qui vous permettra de trouver les valeurs dont vous avez besoin.

Mis à jour, pour répondre au commentaire.

  

Comment ferais-je la jointure associée   considérant que l'utilisateur peut sélectionner   et un nombre arbitraire d'options de   la liste de sélection? SELECT * FROM tblTable   JOIN tblOptions ON tblTable.FK =? le   problème ici est que je dois rejoindre le   plusieurs valeurs.

J'ai répondu à une question similaire ici .

Une méthode consiste à créer une table temporaire et à ajouter chaque option sélectionnée sous forme de ligne à la table temporaire. Ensuite, vous feriez simplement une jointure à votre table temporaire.

Si vous voulez simplement créer votre SQL dynamiquement, vous pouvez faire quelque chose comme ça.

SELECT * FROM tblTable WHERE option IN (selected_option_1, selected_option_2, selected_option_n)

J'ai constaté qu'une fonction de table CLR qui prend votre chaîne délimitée et appelle Split sur la chaîne (renvoyant le tableau sous la forme IEnumerable) est plus performante que tout ce qui est écrit en T-SQL (elle commence à se décomposer lorsque vous avez environ un million d'éléments dans la liste délimitée, mais c'est beaucoup plus loin que la solution T-SQL).

Ensuite, vous pourrez rejoindre la table ou vérifier avec EXISTS.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top