Присоединение к лучшим записям в T-SQL - PullRequest
5 голосов
/ 10 августа 2011
SELECT MD.*, Contact.FirstName 
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID   
JOIN (SELECT TOP 1 * FROM Location WHERE Location.BusID = MD.BusID) L ON L.BusID=MD.BusID
AND L.Deleted = 0
JOIN Contact ON Contact.ContactID = L.PrincipalID

Я использую SQLSERVER 2008 и пытаюсь написать этот оператор SQL. Есть несколько мест для бусида, и я хочу присоединиться только к первому найденному. Я получаю сообщение об ошибке "Location.BusID = MD.BusID", поскольку MD.BusID не может быть привязан. Можно ли использовать таблицу MD во вложенном выборе select в этом соединении или есть другой способ сделать это?

Я собираюсь поместить данные, используя вложенные запросы в список столбцов, чтобы быстро получить контактные данные.

Ответы [ 4 ]

9 голосов
/ 10 августа 2011

Было бы проще, я думаю, иметь подзапрос полного набора результатов:

SELECT MD.*, Contact.FirstName 
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID   
JOIN (SELECT BusID, MAX(PrincipalID)
      FROM Location
      WHERE Deleted = 0
      GROUP BY BusID) L ON L.BusID=MD.BusID
JOIN Contact ON Contact.ContactID = L.PrincipalID

Вы по-прежнему получаете одну запись на BusID в JOIN, но это не коррелирует.

4 голосов
/ 10 августа 2011
SELECT MD.*, Contact.FirstName  
FROM MerchantData MD 
JOIN Merchant M ON M.MerchID = MD.MerchID    
CROSS APPLY (SELECT TOP 1 * FROM Location WHERE BusID = MD.BusID AND DELETED = 0) L
JOIN Contact ON Contact.ContactID = L.PrincipalID 
2 голосов
/ 10 августа 2011

Это случай проблемы "top n per group".Этот вопрос поможет вам:

Запрос SQL Server выберите 1 из каждой подгруппы

Вы захотите сделать что-то вроде этого:

SELECT MD.* ,
       Contact.FirstName 
FROM MerchantData MD
JOIN Merchant     M ON M.MerchID = MD.MerchID   
JOIN ( select * ,
              seq = rank() over( partition by BusID order by BusID , ... )
       from Location
       where L.Deleted = 0
     ) L on L.BusID = MD.BusID
        and seq     = 1
JOIN Contact ON Contact.ContactID = L.PrincipalID

Выражение виртуальной таблицы должно возвращать не более 1 местоположения на BusID (0, если у BusID нет не удаленных местоположений).

0 голосов
/ 10 августа 2011

Чтобы попытаться выделить ошибку, я бы попробовал. Проверьте, может ли он соответствовать Location.BusID = MD.BusID.

    SELECT MD.*, Contact.FirstName 
    FROM MerchantData MD
    JOIN Merchant M ON M.MerchID = MD.MerchID   
    JOIN Location On Location.BusID = MD.BusID 

Вы не используете *, поэтому используйте

    SELECT TOP 1 Location.BusID FROM Location WHERE Location.BusID = MD.BusID 

Как только синтаксис заработает.

Вы знаете, что после того, как вы получите эту работу, она будет соответствовать только первой строке, а затем проверит, удалена ли она. Проблема в том, что без порядка по «первой» строке произойдет произвольно. Даже с кластеризованным индексом для таблицы не существует гарантированной сортировки без предложения order by. Чтобы получить повторяемый ответ, вам нужна сортировка. Но если вы сортируете и хотите только верхний ряд, то MAX или MIN и группа будут более прямыми.

Если вы хотите, чтобы бизнес имел одно или несколько удаленных местоположений, то должны работать следующие правила, но вам нужно разбить столбцы для группы по. Если два удаленных местоположения имеют различное имя контакта, оно сообщит о каждом. Так что это может быть не то, что вы ищете.

    SELECT MD.col1, MD.col2, Contact.FirstName 
    FROM MerchantData MD
    JOIN Merchant M ON M.MerchID = MD.MerchID   
    JOIN Location L
       ON  L.BusID = MD.BusID
       AND L.Deleted = 0
    JOIN Contact ON Contact.ContactID = L.PrincipalID 
    GROUP BY MD.col1, MD.col2, Contact.FirstName 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...