7
votes

SQL Server Inscrit dans l'ordre

J'ai 2 chaîne en entrée, par exemple '1,5,6' et '2,89,9' avec le même nombre d'éléments (3 ou plus). Ces 2 chaînes que je veux faire une "join ordonnée" comme xxx

J'ai pensé à attribuer un numéro de rive et faisait une jointure entre 2 résultat défini comme xxx

est-ce une la meilleure pratique jamais?


0 commentaires

3 Réponses :


13
votes

Lorsque dbo.split () renvoie l'ensemble de données, rien que vous ne puissiez attribuer la ligne_number que vous voulez (en fonction de leur commande dans la chaîne) avec une certitude absolue. SQL NE JAMAIS GARANTIES UNE COMMANDER SANS COMMANDER PAR Compte relatif aux données.

avec vous astuce d'utiliser (sélectionnez 0) pour commander par vous pouvez souvent Obtenez les bonnes valeurs . Probablement très souvent. Mais c'est jamais garanti . Une fois de temps en temps, vous sera obtenez le mauvais ordre.

Votre meilleure option consiste à recoder dbo.split () pour affecter une ligne_number lorsque la chaîne est analysée. Ce n'est qu'alors que pouvez-vous savoir avec 100% de certitude que le rang_number correspond vraiment à la position de l'élément dans la liste.

Alors vous les rejoignez comme vous le souhaitez et obtenez les résultats que vous souhaitez.


Autre que cela, l'idée me semble bien. Bien que vous souhaitiez envisager une jointure extérieure si une liste peut être plus longue que l'autre.


2 commentaires

Oui, il est correctement que vous dites. Et fait une jointure extérieure complète C'est une meilleure pratique;). Mais j'ai pensé qu'il y avait une "commande de commande" particulière :-)


Oui, un cas similaire où SELECT 0 Tampers avec l'ordre souhaité est lors de la sélection d'une table dérivée commandée: Stackoverflow .COM / Q / 18961789/521799



7
votes

Vous pouvez le faire comme ça aussi aussi

​​Considérez votre fonction Split Split, comme celle-ci: P>

SELECT
    *
FROM
    dbo.Split('1,5,6',',') AS a
    JOIN dbo.Split('2,89,9',',') AS b
        ON a.pn=b.pn


5 commentaires

@Arrion - Savez-vous que cette approche garantit l'ordre dans lequel les enregistrements sont insérés? Je crois comprendre que les mêmes considérations donnent au traitement parrallèle, etc., s'appliqueraient ici: Vous n'avez pas spécifié de commande par, et les données peuvent (mais pas être inséré dans un ordre différent auquel il apparaît dans la chaîne. S'il y a des références que vous avez qui donne de telles garanties, j'aimerais les voir, car je préférerais cette approche à l'ivresse à travers la chaîne et crée explicitement la valeur d'identité moi-même. Je veux juste que garantie :)


Non, je ne peux pas garantir l'ordre d'ordre des enregistrements. Je crois comprendre que cela insérera la commande fournie dans la chaîne. Mais je ne peux pas garantir l'ordre d'insertion. Je viens de donner à l'Op une approche différente de sa requête.


Vous obtenez une meilleure performance avec une fonction fractionnée récursive correctement écrite


Bon à savoir .. Mettez à jour la réponse


Je prendrais un Article de KB assez ancien à implique qu'il y a Aucune garantie sur laquelle des lignes ne seront attribuées que les valeurs identité pendant que Insérer , sauf si vous ajoutez un ordre par .



0
votes

Merci à la suggestion d'Arion. C'est très utile pour moi. J'ai modifié la fonction un peu pour prendre en charge le type de chaîne d'entrée Varcharner (max) et une longueur maximale de 1000 pour la chaîne de délimitation. En outre, a ajouté un paramètre pour indiquer si vous avez besoin de la chaîne vide dans le retour final.

pour la question de Matbailie, car il s'agit d'une fonction inline, vous pouvez inclure la colonne PN dans la requête extérieure qui appelle cette fonction. P>

Create function [dbo].[udf_split] (
    @ListString nvarchar(max),
    @Delimiter  nvarchar(1000),
    @IncludeEmpty bit) 
Returns @ListTable TABLE (ID int, ListValue varchar(max))
AS
BEGIN
    Declare @CurrentPosition int, @NextPosition int, @Item nvarchar(max), @ID int
    Select  @ID = 1,
            @ListString = @Delimiter+ @ListString + @Delimiter,
            @CurrentPosition = 1+LEN(@Delimiter)

    Select  @NextPosition = Charindex(@Delimiter, @ListString, @CurrentPosition)
    While   @NextPosition > 0 Begin

        Select  @Item = Substring(@ListString, @CurrentPosition, @NextPosition-@CurrentPosition)
        If      @IncludeEmpty=1 or Len(LTrim(RTrim(@Item)))>0 Begin 
                Insert Into @ListTable (ID, ListValue) Values (@ID, LTrim(RTrim(@Item)))
                Set @ID = @ID+1
        End
        Select  @CurrentPosition = @NextPosition+LEN(@Delimiter), 
                @NextPosition = Charindex(@Delimiter, @ListString, @CurrentPosition)
    End
    RETURN
END


0 commentaires