2016-11-18 4 views
0

J'ai 3 tables (hypothétiques).SqlServer Many to Many ET

[1]

  1. Photos (une liste de photos)
  2. Attributs (choses qui décrivent les photos)
  3. PhotosToAttributes (une table pour relier la première 2)

Je veux récupérer les noms de toutes les photos qui ont une liste d'attributs. Par exemple, toutes les photos comportant un éclairage sombre et des portraits (AttributeID 1 et 2). Ou, par exemple, toutes les photos qui ont un éclairage sombre, sont des portraits et ont été prises lors d'un mariage (AttributeID 1 et 2 et 5). Ou n'importe quel nombre arbitraire d'attributs.

L'échelle de la base de données sera peut-être 10 000 lignes dans Photos, 100 lignes dans les attributs et 100 000 lignes dans PhotosToAttributes. Cette question SQL: Many-To-Many table AND query est très proche. (Je pense.) J'ai aussi lu les réponses liées à la performance. Cela conduit à quelque chose comme ce qui suit. Mais, comment puis-je obtenir le nom au lieu de PhotoID? Et probablement mon code (C#) construira cette requête et ajustera la liste d'attribut et comptera si nécessaire? Je suis un peu analphabète de base de données (cela fait 20 ans que j'ai pris une classe de base de données); Je ne suis même pas sûr que ce soit un bon moyen de structurer les tables. Je voulais pouvoir ajouter de nouveaux attributs et des photos à volonté sans changer le code d'accès aux données.

Répondre

0

C'est probablement un moyen raisonnable de structurer la base de données. Une alternative consisterait à conserver tous les attributs sous la forme d'une liste délimitée dans un champ varchar, mais cela entraînerait des problèmes de performances lors de la recherche dans le champ.

Votre code est proche, de le prendre à l'étape finale, vous devez simplement joindre les deux autres tables comme ceci:

Select p.Name, p.PhotoID 
    From Photos As p 
    Join PhotosToAttributes As pta On p.PhotoID = pta.PhotoID 
    Join Attributes As a On pta.AttributeID = a.AttributeID 
    Where a.Name In ('Dark Light', 'Portrait', 'Wedding') 
    Group By p.Name, p.PhotoID 
    Having Count(*) = 3; 

En adhérant à la table Attributes comme cela signifie que vous pouvez rechercher des attributs par leur nom, au lieu de leur ID.

+0

L'alternative que vous mentionnez est non-relationnelle et devrait être découragée dans les termes les plus forts possible. Bref, ne fais jamais ça jamais. – RBarryYoung

0

Pour créer la première vue de votre Jointures:

create view vw_PhotosWithAttributes 
as 
select 
    p.PhotoId, 
    a.AttributeID, 
    p.Name PhotoName, 
    a.Name AttributeName 
from Photos p 
inner join PhotosToAttributes pa on p.PhotoId = pa.PhotoId 
inner join Attributes a on a.AttributeID = pa.AttributeID 

Vous pouvez demander facilement attribut, nom, id, mais ne pas oublier de bien champ d'index.