LEFT Join返回重复行

时间:2016-09-26 18:57:28

标签: sql-server

我有以下查询

SELECT
    [crm_quote_id],
    ISNULL(contact.Id, 2482) AS contactId,
    [crm_quote_company],
    [crm_quote_started_by_name],
    [crm_date_started],
    [crm_quote_status],
    [crm_quote_validity],
    [crm_quote_payment_terms],
    [address_line_1],
    [crm_quote_message_1],
    [crm_quote_message_2],
    [crm_quote_message]
FROM 
    [crmlive].[dbo].[crm_quotes] quote
LEFT JOIN 
    [CRMLiveWarwick].[dbo].[Contacts] contact 
      ON quote.address_line_1    = concat(contact.Firstname, ' ', contact.Surname)                                           
     AND quote.crm_quote_company = contact.CompanyId

[CRMLiveWarwick].[dbo].[Contacts]联系人在同一家公司内有重复的全名(名字+''+姓氏)。这意味着它返回更多行,因为它们匹配。

我试过

SELECT
    [crm_quote_id],
    MAX(ISNULL(contact.Id, 2482)) AS contactId,
    [crm_quote_company],
    [crm_quote_started_by_name],
    [crm_date_started],
    [crm_quote_status],
    [crm_quote_validity],
    [crm_quote_payment_terms],
    [address_line_1],
    [crm_quote_message_1],
    [crm_quote_message_2],
    [crm_quote_message]
FROM 
    [crmlive].[dbo].[crm_quotes] quote
LEFT JOIN 
    [CRMLiveWarwick].[dbo].[Contacts] contact 
      ON quote.address_line_1 = concat(contact.Firstname, ' ', contact.Surname)                                            
     AND quote.crm_quote_company = contact.CompanyId
GROUP BY 
    quote.crm_quote_id

所以我得到了最大的联系人。但是我发现了以下错误

  

列'crmlive.dbo.crm_quotes.crm_quote_company'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

只是给出一些上下文我将数据从旧数据库迁移到新数据库。旧数据库(crmlive.dbo.crm_quotes)没有联系人ID,但我可以通过查询包含名字和姓氏字段的联系人表来找到它。

4 个答案:

答案 0 :(得分:3)

您需要在group by子句中添加所有这些

[crm_quote_company],
[crm_quote_started_by_name],
[crm_date_started],
[crm_quote_status],
[crm_quote_validity],
[crm_quote_payment_terms],
[address_line_1],
[crm_quote_message_1],
[crm_quote_message_2],
[crm_quote_message]

更新了查询

SELECT
    [crm_quote_id],
    MAX(ISNULL(contact.Id, 2482)) AS contactId,
    [crm_quote_company],
    [crm_quote_started_by_name],
    [crm_date_started],
    [crm_quote_status],
    [crm_quote_validity],
    [crm_quote_payment_terms],
    [address_line_1],
    [crm_quote_message_1],
    [crm_quote_message_2],
    [crm_quote_message]
FROM [crmlive].[dbo].[crm_quotes] quote
LEFT JOIN [CRMLiveWarwick].[dbo].[Contacts] contact
    ON quote.address_line_1 = concat(contact.Firstname, ' ', contact.Surname)
    AND quote.crm_quote_company = contact.CompanyId
GROUP BY    quote.crm_quote_id,
            [crm_quote_company],
            [crm_quote_started_by_name],
            [crm_date_started],
            [crm_quote_status],
            [crm_quote_validity],
            [crm_quote_payment_terms],
            [address_line_1],
            [crm_quote_message_1],
            [crm_quote_message_2],
            [crm_quote_message]

答案 1 :(得分:1)

另一种选择是使用ROW_NUMBER并选择第一个等级。像这样:

;WITH cte AS (
    SELECT
        [crm_quote_id],
        ISNULL(contact.Id, 2482) AS ContactId,
        [crm_quote_company],
        [crm_quote_started_by_name],
        [crm_date_started],
        [crm_quote_status],
        [crm_quote_validity],
        [crm_quote_payment_terms],
        [address_line_1],
        [crm_quote_message_1],
        [crm_quote_message_2],
        [crm_quote_message],
        ROW_NUMBER() OVER (PARTITION BY quote ORDER BY ISNULL(contact.Id, 2482)) AS RowNo
    FROM 
        [crmlive].[dbo].[crm_quotes] quote
    LEFT JOIN 
        [CRMLiveWarwick].[dbo].[Contacts] contact ON quote.address_line_1 = concat(contact.Firstname, ' ', contact.Surname)
                                                  AND quote.crm_quote_company = contact.CompanyId
)
SELECT cte.*        -- or better, just the columns you need
FROM cte
WHERE RowNo = 1

性能可能比所有这些列的分组稍差,但它的优点是可以在CTE中轻松添加更多列,而无需为分组而烦恼。

另外,在性能方面,您应该考虑避免使用JOINING VARCHARS,特别是在像quote.address_line_1 = concat(contact.Firstname, ' ', contact.Surname)这样的表达式中,这对于大型集合来说可能非常昂贵。

答案 2 :(得分:1)

我不会join直接Contact,然后加入您想要的group个联系人,例如:

SELECT
    [crm_quote_id],
    max_contactId AS contactId,
    ...
FROM 
    [crmlive].[dbo].[crm_quotes] q LEFT outer JOIN 
    (select
        concat(Firstname, ' ', Surname) as contactname,
        CompanyId,
        MAX(ISNULL(Id, 2482)) AS max_contactId
     from
        [CRMLiveWarwick].[dbo].[Contacts]
     group by
        concat(Firstname, ' ', Surname), CompanyId) c ON 
     q.address_line_1 = contactname  AND 
     q.crm_quote_company = c.CompanyId

答案 3 :(得分:1)

我认为row_number会起作用,但这至少会给你正确的信息 MAX(ISNULL(contact.Id,2482))

SELECT
    [crm_quote_id],
    MAX(ISNULL(contact.Id, 2482)) AS contactId,
FROM 
    [crmlive].[dbo].[crm_quotes] quote
LEFT JOIN 
    [CRMLiveWarwick].[dbo].[Contacts] contact 
      ON quote.address_line_1 = concat(contact.Firstname, ' ', contact.Surname)                                            
     AND quote.crm_quote_company = contact.CompanyId
GROUP BY 
    quote.crm_quote_id