7
votes

TSQL comparant deux ensembles

Lorsque deux ensembles sont donnés

S1 = {A, B, C, D, C, D, A} P>

(IE) P>

Elements in TableA and TableB contains identical sets


2 commentaires

Vous ne voulez pas intersect eux?


BTW, si vous avez besoin de Rechercher pour les ensembles correspondants dans un ensemble Collection , c'est un problème différent, et les solutions ici peuvent ne pas vous aider beaucoup.


6 Réponses :


3
votes

Ma monstruction: xxx


3 commentaires

Coût de la sous-arbitre de 0,0178567 - Un cheveu mieux que la réponse de CMSJR


Mon AEP dit que le STC est 0.01129. Mais là encore, je viens de courir la requête dans son ensemble, sans préparer ces ensembles à l'avance.


J'exécute deux passes pour vérifier que la requête renvoie une sortie valide pour des échantillons de faux et positifs. Je ne posterais pas le coût si la requête ne passe pas les tests préliminaires.



1
votes

pourrait le faire avec sauf et une affaire xxx


5 commentaires

S2 pourrait avoir plus d'articles que S1, mais cette requête affirmerait qu'elles sont identiques.


Certains diraient que les ensembles sont toujours les mêmes, vous pourriez alors affirmer les comptes si vous le souhaitez, ou si vous pouviez faire des checksums de ligne si vous vous ennuyez vraiment.


+1: Sur SQL Server 2005, cette requête a un meilleur coût de sous-arbre de 0,0000459 VS Ma version à l'aide de Intersect (0.0000702). J'imagine que mes versions sont des coûts plus élevés sont dues aux comparaisons de comptage.


Cette requête est incorrecte. Si S2 a toutes les lignes pour correspondre à S1, mais dispose de lignes non amorties supplémentaires, cette requête reviendra toujours avoir des ensembles identiques.


-1 - Je suis d'accord avec @Peter et @emTuCifor que cela donne de faux positifs.



9
votes

Utilisation:

WITH a AS (
  SELECT 'a' AS col
  UNION ALL
  SELECT 'b'
  UNION ALL
  SELECT 'c'
  UNION ALL
  SELECT 'd'),
     b AS (
  SELECT 'b' AS col
  UNION ALL
  SELECT 'c'
  UNION ALL
  SELECT 'd'
  UNION ALL
  SELECT 'a')
SELECT CASE 
         WHEN   COUNT(*) = (SELECT COUNT(*) FROM a) 
            AND COUNT(*) = (SELECT COUNT(*) FROM b) THEN 'yes'
         ELSE 'no'
       END
  FROM (SELECT a.col
          FROM a
        INTERSECT
        SELECT b.col
          FROM b) x 


4 commentaires

Informations très intéressantes sur les coûts des sous-armes.


C'est 2 lectures par table + 1 Join. Est-ce que personne ne sait utiliser comment utiliser Joindre complet ?


@Peter: J'ai couru votre option de jointure complète, il existe une marge de performance extrêmement large entre votre jointure complète et l'utilisation d'intersect ou sauf (sur SS2005 de toute façon). J'imagine que le coût légèrement plus élevé pour l'intersect (VS Nix sauf la version) est due aux comptes pour que le message approprié est affiché.


@Empifier: la join complète est pire en fonction de la valeur de coût du sous-groupe - voir Commentaires respectifs à chaque réponse pour plus de détails.



3
votes

montre, je vais utiliser une jointure croisée. xxx


15 commentaires

Coût de la sous-arbre de 0,0178713 - Le Intersect & sauf Alternatives effectuez plus efficacement.


On dirait une jointure intérieure pour moi.


@CMSJR: Cross Join est pris en charge sur SQL Server 2000 < / a>, je suppose donc que vous voulez dire comment intersect et sauf sont la fonctionnalité de 2005+? Mise à niveau =)


@Peter je n'ai aucune idée de ce dont vous parlez.


@OMG, j'ai clairement supprimé ce commentaire et je n'apprécie pas que vous avez répondu à cela. Mon nouveau commentaire allait être comme suit.


OMG @OMG, où est votre sens de plaisir.


@CMSJR: Désolé, j'étais effronté. Je ne vois pas de problème avec l'utilisation de la croix Join sur SS2K, mais la différence de performance est immense lors de l'utilisation de la fonctionnalité de 2005+.


J'étais effronté aussi, aucune infraction prise (ni j'espère donner) à tout moment. La solution n'est clairement pas performante, cela semblait simplement être une occasion valable si l'inefficace peut sortir de la croix de la croix.


une croix join B Où.val = b.val équivaut à une join intérieure B sur.val = b.val et sera réécrit comme une jointure intérieure par l'optimiseur. Vérifiez les plans d'exécution, ils seront identiques.


Qu'ils sont. Même plan d'exécution Si vous déposez également la jointure. Encore une fois, Cross Rejoindre des antics ne sont qu'un buste ...


@CMSJR: la réponse de Peter est légèrement plus rapide et 2000 - Meilleur candidat SS2K jusqu'à présent.


Merci pour la tête, avez-vous élu dans sa direction générale (et la vôtre)


Ce n'est en réalité pas une croix de joindre comme vous le savez et que vous utilisez les mots croix rejoindre lorsque vous n'étant pas l'intention d'être inutile.


WOW, UH merci de lire tous les commentaires avant d'ajouter le vôtre.


Bien, alors que diriez-vous de cet angle, puisque toutes les variantes réduisent au même plan d'exécution, et mon intention réelle consiste à comparer toutes les valeurs à toutes les autres valeurs, la croix ne joint à la croix expresse plus explicitement cette intention mieux que la jointure intérieure ou la Absence d'un opérateur de jointure?



7
votes

quelque chose comme ceci, en utilisant Joindre complet rejoindre : xxx

Ceci a la vertu de court-circuit lors de la première non-correspondance, contrairement à d'autres solutions qui nécessitent 2 SCAN complètes de chaque table (une fois pour le compte (*), une fois pour la jointure / intersect).

Le coût estimé est nettement inférieur à celui des autres solutions.


4 commentaires

Mon approche initiale. Je suppose que ce n'est pas assez amusant! :)


Coût du sous-arbre réel (pour moi) de 0,0178565 - à peine inférieure à la réponse de Denis, une alternative légèrement meilleure que la réponse de CMSJR ... Contrevoiement de la question de CMSJR sur les alternatives SS2000 .


Bah, tard à la fête, une rejoignée complète allait être ma réponse aussi.


@EmtuCifor: Et quelle partie c'était une fête! Doit être l'heure de la journée de la journée d'I-Bese-A-Distraction.



1
votes

Puisque ce fil m'a été très utile, je pensais partager ma solution.

J'ai eu un problème similaire, peut-être plus généralement applicable que cette comparaison unique. J'essayais de trouver l'identifiant d'un élément qui comptait un ensemble d'éléments d'enfants multi-éléments correspondant à un ensemble de requêtes d'éléments multi-éléments. P>

Les informations de schéma correspondantes sont les suivantes: p>

with solutionids as (
  select y.solutionid from (
     select ss.solutionid, count(ss.solutionid) x 
        from solutions s, solution_sources ss 
        where s.event_id = 110 and ss.solutionid = s.id 
        group by ss.solutionid
  ) y where y.x = ( select count(*) from ss_tmp )
) 
select solutionids.solutionid  from solutionids where
(
select case
   when count(*) = ( select count(*) from ss_tmp ) then true
   else false
   end
    from 
       ( SELECT unitsourceid, alpha FROM solution_sources 
            where solutionid = solutionids.solutionid
          INTERSECT
         SELECT unitsourceid, alpha FROM ss_tmp ) x
)


0 commentaires