requête alternative à cette (éviter DISTINCT)


3

Note: Je travaille avec MSSQL 2008, mais je suppose qu'il est valable pour beaucoup d'autres moteurs DB Je possède ce tableau « Utilisateurs »:

 
UserID User CountryID 
1  user 1 1 
2  user 2 2 
3  user 3 3 
4  user 4 4 
5  user 5 4 
6  user 6 3 

Et ce tableau « Pays "

 
CountryID Country 
1   MX 
2   USA 
3   CAN 
4   ENGLAND 

Comme vous pouvez le voir, chaque utilisateur appartient à un pays.

Si je veux savoir, tous les pays où j'ai au moins, un utilisateur sur la table des utilisateurs, en ce moment je fais cette requête:

select distinct country 
from Users inner join 
countries on users.CountryID=countries.CountryID 

et d'atteindre l'ensemble de résultats suivant:

 
CAN 
ENGLAND 
MX 
USA 

Ce qui est en effet, tous les pays, où j'ai au moins un utilisateur sur les utilisateurs de table muy.

Mon doute est, est possible d'atteindre l'ensemble des résultats ci-dessus, à l'aide de « DISTINCT », je veux dire que l'utilisation REJOINT et conditions?

Ici, il est des scripts de DDL:

 
USE [TEST] 
GO 
/****** Object: Table [dbo].[Users] Script Date: 09/21/2012 16:21:14 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Users](
    [UserID] [int] NULL, 
    [User] [nvarchar](50) NULL, 
    [CountryID] [int] NULL 
) ON [PRIMARY] 
GO 
INSERT [dbo].[Users] ([UserID], [User], [CountryID]) VALUES (1, N'user 1', 1) 
INSERT [dbo].[Users] ([UserID], [User], [CountryID]) VALUES (2, N'user 2', 2) 
INSERT [dbo].[Users] ([UserID], [User], [CountryID]) VALUES (3, N'user 3', 3) 
INSERT [dbo].[Users] ([UserID], [User], [CountryID]) VALUES (4, N'user 4', 4) 
INSERT [dbo].[Users] ([UserID], [User], [CountryID]) VALUES (5, N'user 5', 4) 
INSERT [dbo].[Users] ([UserID], [User], [CountryID]) VALUES (6, N'user 6', 3) 
/****** Object: Table [dbo].[Countries] Script Date: 09/21/2012 16:21:14 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Countries](
    [CountryID] [int] NULL, 
    [Country] [nvarchar](50) NULL 
) ON [PRIMARY] 
GO 
INSERT [dbo].[Countries] ([CountryID], [Country]) VALUES (1, N'MX') 
INSERT [dbo].[Countries] ([CountryID], [Country]) VALUES (2, N'USA') 
INSERT [dbo].[Countries] ([CountryID], [Country]) VALUES (3, N'CAN') 
INSERT [dbo].[Countries] ([CountryID], [Country]) VALUES (4, N'ENGLAND') 
INSERT [dbo].[Countries] ([CountryID], [Country]) VALUES (5, N'BRAZIL') 

  0

l'importance de votre échantillon de données serait améliorée si vous ajoutez un pays à la table des pays Ce n'est pas référencé par un utilisateur.actuellement, le jeu de résultats de la requête que vous recherchez est le même que 'select Country from Countries'. 22 sept.. 122012-09-22 08:53:37

6

Les deux scripts de la réponse de RThomas sont utiles.Vous pouvez également utiliser GROUP BY, qui offre un avantage similaire aux méthodes de RThomas, tout en conservant un formulaire similaire à votre requête d'origine.

select country 
from Users inner join
countries on users.CountryID=countries.CountryID
GROUP BY countries.CountryID, countries.country;

La raison pour laquelle vous groupez par CountryID est que c'est la clé primaire de votre table de pays, ce qui donne à Optimiseur de requêtes de meilleures options.

... sauf que ce n'est pas dans vos scripts.

Placez des PK (avec des index clusterisés) sur vos tables et établissez une relation FK entre elles.Index CountryID dans la table Users et insérez un index unique dans le champ Country.

Une fois que vous avez terminé tout cela, utiliser DISTINCT à votre guise vous donnera le plan d’exécution idéal.

  0

de bons commentaires sur la fourniture d'optimiseur avec l'aide pour en tirer le meilleur parti comme ... des informations très utiles. +1 24 sept.. 122012-09-24 01:23:40


4

Vous pouvez obtenir ce même jeu de résultats avec les éléments suivants:

select country from countries where exists 
    (select countryid from users 
     where users.countryid = country.countryid) 

OU

select country from countries where countryid in 
    (select countryid from users) 

Aucune de ces utiliser distincts mais d'autres que je ne sais pas combien ils sont "meilleurs".


1

Et il y a l'approche de base GROUP BY dans le n -table et puisJOIN au 1 -table dans une relation 1: n. Ceci est souvent plus rapide que de se joindre avant le regroupement, mais je ne suis pas sûr que cela fait une différence pour SQL serveur 2008.

SELECT country 
FROM (
    SELECT CountryID 
    FROM Users 
    GROUP BY CountryID 
    ) AS u 
JOIN countries AS c ON u.CountryID = c.CountryID