2009-05-08 9 views
1

Supposons que j'ai deux tables ... Foo et Bar. Ils contiennent les données suivantes.T/SQL Puzzle - Comment se joindre pour créer une relation un-à-un pour deux tables non liées?

Table Foo: 
Foo_Id 
------ 
100 
101 

Table Bar: 
Bar_Id 
------ 
200 
201 

Comme vous pouvez le voir, chaque table a deux enregistrements. Je voudrais joindre ces tables ensemble d'une manière où ils renvoient deux disques; le but ultime est de créer une relation un à un pour ces enregistrements, même si à cet état, ils n'ont pas cette relation. Les résultats de ces données iraient dans la table Foo_Bar pour stocker cette nouvelle relation.

Idéalement, la sortie ressemblerait à ce qui suit.

Foo_Id Bar_Id 
------ ------ 
100  200 
101  201 

Ce code sera utilisé dans une procédure stockée T/SQL. Je pourrais écrire ceci facilement avec une boucle while, mais je préférerais ne pas utiliser une boucle while car l'application du monde réel aura beaucoup plus de données que quatre enregistrements et sera appelée par plusieurs utilisateurs plusieurs fois par jour.

Merci d'avance!

EDIT:

Il est plus ou moins un problème d'inventaire ... J'ai 100 tranches de pizza et 100 personnes qui disent qu'ils veulent une tranche de pizza. La table Foo_Bar est essentiellement un moyen d'attribuer une part de pizza par personne. La table existe et cette solution chargera les données pour la table.

+0

A). Je pense que vous avez la réponse dans votre question B). pourquoi voudriez-vous créer une relation où l'on n'existe pas? Soit il y a une relation et elle devrait être modélisée de façon appropriée ou non. – annakata

+0

Quelle est la relation entre les données?Est-ce que n'importe quel Foo_Id peut contenir n'importe quel Bar_Id? –

+0

C'est plus ou moins un problème d'inventaire ... J'ai 100 tranches de pizza et 100 personnes qui me disent qu'elles veulent une part de pizza. La table Foo_Bar est essentiellement un moyen d'attribuer une part de pizza par personne. La table existe et cette solution chargera les données pour la table. – proudgeekdad

Répondre

5

essayez ceci:

declare @Foo table (Foo_Id int) 
INSERT INTO @Foo VALUES (100) 
INSERT INTO @Foo VALUES (101) 
declare @Bar table (Bar_Id int) 
INSERT INTO @Bar VALUES (200) 
INSERT INTO @Bar VALUES (201) 


SELECT 
    dt_f.Foo_Id 
     ,dt_f.RowNumber 
     ,dt_b.Bar_Id 
    FROM (SELECT 
       Foo_Id, ROW_NUMBER() OVER(ORDER BY Foo_Id) AS RowNumber 
       FROM @Foo 
     ) dt_f 
     INNER JOIN (SELECT 
         Bar_Id, ROW_NUMBER() OVER(ORDER BY Bar_Id) AS RowNumber 
         FROM @Bar 
        ) dt_b ON dt_f.RowNumber=dt_b.RowNumber 
2

select foo_id, bar_id de jointure foo bar foo_id = (bar_id -100)

+0

cela ne fonctionnera que pour cet exemple de données –

+0

il a fourni un moyen de répondre au problème qui a été posté à l'origine. –

0

sélection de chaque table comme une instruction select imbriquée avec une fonction de rang, puis rejoindre le rang.

select foo_id, bar_id 
from (select foo_id, rank() over (partition by foo_id order by foo_id) as [Rank] from foo) f 
left join (select bar_id, rank() over (partition by bar_id order by bar_id) as [Rank] from bar) b 
on f.Rank = b.Rank 
+0

lorsqu'il est exécuté sur les données exemple données, il renvoie 4 lignes. Vous devez supprimer "Partition by foo_id" et "partition by bar_id" pour le faire fonctionner correctement. J'utilise la même approche sing row_number(), voir ma solution. –

2

Dans l'exemple que vous avez donné, vous pourriez être en mesure d'exploiter le fait que bar_id = 100 + foo_id

 
select foo.foo_id, bar.bar_id 
from foo inner join bar on foo.foo_id +100 = bar.bar_id 

.. mais peut-être est juste une simplification dans votre exemple?

S'il n'y a aucun lien de parenté entre les ID, alors ce n'est plus vraiment les données relationnelles, et il n'y a aucun moyen facile de joindre les lignes dans une base de données relationnelle. Dans ce cas, vous devrez ajouter une nouvelle colonne à l'une des tables et ajouter une clé étrangère pour que les données deviennent.

+0

cela ne fonctionnera que pour les données d'échantillon simples –

+0

ouais, pensé qu'il pourrait. La deuxième partie alternative de ma réponse est d'ajouter une nouvelle colonne, mais je sais que ce n'est pas beaucoup mieux soit:) – codeulike

2

L'affectation à l'inventaire est généralement une opération à une ligne à la fois. Utiliser des ensembles pour cela est génial, mais c'est un peu un «paradigme de traitement par lots». J'imagine que diverses personnes se mettent en ligne et achètent des pizzas à partir de la table d'inventaire. Mssql a quelques astuces utiles pour ce modèle get-next-available-item - regardez l'indice READPAST. Pour acquérir une pizza que vous pourriez faire quelque chose comme

UPDATE mytable WITH (READPAST) SET AcquiringUserID = @userId where AcquiringUserId is null 
+0

Trouvé un article qui va sur ce genre d'approche - http://www.mssqltips.com/tip.asp? Astuce = 1257 – ahains