2010-11-12 4 views
0

J'utilise t-sql. J'ai ce que je pensais être une recherche facile. Il existe une relation 1-à-plusieurs entre SalesPerson et TradeShow. 1 vendeur aurait pu aller à de nombreux salons. Je dois être capable de chercher sur le SalePerson. Je dois également être en mesure de faire une recherche sur le dernier salon auquel ils ont assisté. Je pensais que je serais en mesure de faire de simples rencontres et groupes sur leur dernier salon, mais je ne peux pas afficher la ville ou l'État.Comment effectuer une recherche sur une relation 1-à-plusieurs lorsque les critères peuvent figurer sur l'une ou l'autre des tables?

SELECT  SalePersonID, FirstName, LastName, TradeShow.DateLastWent 
FROM   SalesPerson INNER JOIN 
(SELECT  SalePersonID, MAX(DateLastWent) AS DateLastWent 
    FROM TradeShow 
GROUP BY SalesPersonID) AS TradeShow ON SalesPerson.SalePersonID= TradeShow.SalePersonID 

Ce travail, mais le salon a aussi la ville et l'État. Je dois pouvoir rechercher et afficher la ville et l'état. Mais si je les inclue dans la sous-requête, je dois les inclure dans une fonction agrégée, et si je fais cela, j'obtiens la ville et l'état incorrects.

Les tables sont simples

SALEPERSON SalesPersonID PK prenom lastname

TRADESHOW tradeshowID PK datelastwent ville état SalesPersonID FK

Répondre

0

Vous pouvez joindre deux fois TradeShow:

SELECT  SalePersonID, FirstName, LastName, TS1.DateLastWent, 
    TS2.City, TS2.State 
FROM   SalesPerson INNER JOIN 
(SELECT  SalePersonID, MAX(DateLastWent) AS DateLastWent 
FROM TradeShow 
GROUP BY SalesPersonID 
) AS TS1 ON (SalesPerson.SalePersonID= TradeShow.SalePersonID) 
INNER JOIN TradeShow TS2 ON 
(TS2.SalePersonID = TS1.SalePersonID AND TS2.DateLastWent = TS1.DateLastWent) 
WHERE TS2.City = 'CityName' 
+0

Cela nécessitera également une analyse de table supplémentaire sur l'utilisation de quelque chose avec ROW_NUMBER() OVER (ORDER BY ~). Alors peut-être en mesure d'optimiser? –

+0

Notez que vous allez avoir des problèmes avec cela s'ils vont à deux spectacles dans une journée. – Stu

+0

Je ne pense pas que ce soit une analyse de table du tout (il y a un FK sur SalePersonId, et j'espère qu'il y a un index sur ce champ aussi - au moins il est recommandé de créer un index sur les colonnes FK), dans le pire des cas, il s'agira d'index scan + lookup. – a1ex07

0

Il y a probablement une façon plus élégante de résoudre ceci, mais ma première pensée est de simplement saisir le dernier record de TradeShow à j oin avec

SELECT SalePersonID, FirstName, LastName, TradeShow.DateLastWent 
    FROM SalesPerson 
     INNER JOIN (
        SELECT * 
        FROM (
          SELECT TradeShowId, DateLastWent, City, State, SalesPersonId 
          FROM TradeShow 
         ORDER BY datelastwent DESC 
         ) 
        WHERE ROWNUM <= 1 
       ) ON SalesPerson.SalesPersonId = TradeShow.SalesPersonId 

Modifier

Oops ... joué avec Oracle façon trop

ROW_NUMBER() OVER(order by date) or SELECT TOP X 

serait THW SQL Server pour le faire ... n'ont pas instance de SQL-Server en cours d'exécution, mais assez sûr que la syntaxe finit par être quelque chose comme

SELECT SalePersonID, FirstName, LastName, TradeShow.DateLastWent 
    FROM SalesPerson 
     INNER JOIN ( 
        SELECT TradeShowId, DateLastWent, City, State, SalesPersonId, ROW_NUMBER() OVER(PARTITION BY TradeShow.SalesPersonId ORDER BY DateLastWent DESC) RowNumber 
        FROM TradeShow 
       ) ON SalesPerson.SalesPersonId = TradeShow.SalesPersonId AN TradeShow.RowNumber = 1 
+0

Il n'y a pas ROWNUM dans SQL Server. – Stu

+0

@Stu - Merci, avait Oracle dans ma tête - mise à jour des détails pour refléter ROW_NUMBER() OVER ou TOP –

+0

Oracle dans votre tête? Pauvre chose! Quoi qu'il en soit, cela devrait fonctionner - en 2005 ou plus tard. – Stu

1

Reformulez-le: ce que vous voulez, c'est le vendeur, plus les informations de la dernière émission à laquelle il a participé.

Select 
    SalePersonID, 
    FirstName, 
    LastName, 
    TradeShow.DateLastWent, 
    TradeShow.City, 
    TradeShow.State 
From 
    SalesPerson 
    Inner Join TradeShow 
    On SalesPerson.SalePersonID = TradeShow.SalePersonID 
Where 
    TradeShow.TradeShowID = 
    (Select Top 1 Latest.TradeShowID 
    From TradeShow As Latest 
    Where SalesPerson.SalePersonID = Latest.SalePersonID 
    Order By Latest.DateLastWent Desc) 
+0

Une note sur la solution utilisant ROW_NUMBER() OVER (~) est que cela nécessitera une analyse de table complète supplémentaire lors de l'exécution de la requête, ce qui est légèrement moins efficace. –