2009-09-13 4 views
0

J'ai deux auteurs de tables SQL Server, et des articles où la clé primaire des auteurs (AuthorID) est une clé étrangère dans la table des articles pour représenter une simple relation un-à-plusieurs entre les auteurs et les articles. Maintenant, voici le problème, je dois publier une recherche de texte intégral sur la table des auteurs en fonction des prénoms, des noms et des colonnes de la biographie. La recherche en texte intégral fonctionne génial et classement et tout. Maintenant, j'ai besoin d'ajouter un critère supplémentaire à ma recherche, j'ai besoin que tous les contributeurs non-articles soient ignorés de la recherche. Pour y parvenir, j'ai choisi de créer une vue avec tous les contributeurs qui ont des articles et de chercher dans cette vue. Donc, j'ai créé la vue de cette façon:
Sélectionner uniquement les auteurs qui ont des articles?

Create View vw_Contributors_With_Articles 
AS 
Select * from Authors 
Where Authors.ContributorID 
IN (Select Distinct (Articles.ContributorId) From Articles) 

Il travaille, mais je n'aime vraiment pas la chose sous-requête. La jointure m'obtient tous les authorIDs redondants, essayé distinctement mais n'a pas fonctionné avec la colonne de biographie car c'est le type est ntext. Grouper par ne le ferait pas pour moi parce que j'ai besoin de toutes les colonnes pas un ensemble d'entre eux.

Que pensez-vous les gars? Comment puis-je améliorer cela?

Répondre

5

Un EXISTE permet des entrées en double potentiels lorsque plusieurs articles par auteur:

Select * from Authors 
Where EXISTS (SELECT * 
    FROM Articles 
    WHERE Articles.ContributorId = Authors.ContributorId) 

Edit: Pour clarifier les choses, vous ne pouvez pas DISTINCT sur des colonnes ntext. Ainsi, vous ne pouvez pas avoir de solution JOIN, sauf si vous utilisez une table dérivée sur les articles dans JOIN et évitez d'utiliser directement les articles. Ou vous convertissez le ntext en nvarchar (max). EXISTS ou IN est votre seule option.

Edit 2:

... à moins que vous vraiment envie d'utiliser un JOIN et vous avez SQL Server 2005 ou supérieur, vous pouvez CAST et DISTINCT (total) afin d'éviter plusieurs lignes dans la sortie .. .

select DISTINCT 
    Authors.ContributorID, 
    Authors.AnotherColumn, 
    CAST(Authors.biography AS nvarchar(max)) AS biography, 
    Authors.YetAnotherColumn, 
    ... 
from 
    Authors 
inner join 
    Articles on 
    Articles.ContributorID = Authors.ContributorID 
+0

La sous-sélection devrait être écrite comme 'select 1 from articles ...'. Vous ne voulez rien retirer du backend, vous voulez juste savoir si quelque chose est là. – dland

+0

@dland: Ceci est un mythe. NULL, 1, ou *: pas de différence avec le plan. – gbn

+0

@ gbn- +1, en particulier sur le mythe de SELECT 1. – RichardOD

0

Vous voulez une jointure

select 
    * 
from 
    Authors 
inner join 
    Articles on 
    Articles.ContributorID = Authors.ContributorID 

Ce sera de retour auteurs seulement qui ont une entrée sur la table Articles, compensée par ContributorID.

+1

... et duplique si plusieurs articles et toutes les colonnes article – gbn

+0

Qu'en est-il des valeurs en double lorsqu'un auteur a plus d'un article? – Galilyou

+0

Oui mais cela pourrait facilement être réparé avec un DISTINCT. – RichardOD

0

Sélectionnez les contributorIDs distincts de la table des articles pour obtenir les auteurs qui ont écrit un article, et se joindre à la table des auteurs à cette requête - si quelque chose comme

select distinct Articles.contributorID, Authors.* 
from Articles 
join Authors on Articles.contributerID = Authors.ContributerId 
+1

Ne fonctionne pas: ne peut pas DISTINCT sur ntext. Et pourquoi 2 colonnes ContributorId dans la sortie? – gbn

+0

Les deux colonnes étaient juste pour rendre plus clair ce qu'il fait. J'ai manqué le ntext, les excuses - mais c'est un schéma bizarre, normalement je m'attendrais à voir les noms d'auteur dans un domaine de leur propre, pas dans un champ de texte. – blowdart

+0

@Blowdart: c'est une colonne "biographie" je pense – gbn