一起使用 SQL JOIN 和 UNION

Posted

技术标签:

【中文标题】一起使用 SQL JOIN 和 UNION【英文标题】:Using SQL JOIN and UNION together 【发布时间】:2011-10-28 07:01:10 【问题描述】:

好的,我很难理解为什么会出现以下行为。

我有一个“交易标头”表和“交易明细”表。对于某个函数,明细表需要进行一些规范化来提取“Remark”数据。每条明细记录中最多可以有 3 个备注,由 TranRemark1、TranRemark2 和 TranRemark3 列指定。

我将以下查询放在一起,认为它会起作用,但它返回的记录数不正确。

SELECT  
b.ClientName,
a.TranID,
a.TranRemark1,
a.TranDateOfService,
a.TranPayment   
FROM
(select TranRemark1, TranID from TranDetail
union all
select TranRemark2, TranID from TranDetail
union all
select TranRemark3, TranID from TranDetail) AS a
LEFT JOIN TranHeader AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;

我得到的结果集基于与 ClientName 匹配的 TranHeader 记录数,而不是与 TranDetail 中的 where 子句匹配的记录数。例如,如果客户“Acme Inc.”头表中有 3 条记录,我使用上述查询获取备注代码“1234”(仅匹配 TranDetail 中的 1 条记录)结果集列出了 3 次正确的记录。

编辑 所以我希望从上面的例子中得到这样的结果集:

ClientName--TranID--TranRemark1--TranDateOfService--TranPayment
Acme Inc    ADC11   1234         8-16-2011          45.11    

我得到的是这样的:

ClientName--TranID--TranRemark1--TranDateOfService--TranPayment
Acme Inc    ADC11   1234         8-16-2011          45.11    
Acme Inc    ADC11   1234         8-16-2011          45.11  
Acme Inc    ADC11   1234         8-16-2011          45.11  

请记住,在 TranHeader 中可以有多个客户记录。

我尝试了正确的完全加入,但结果都一样。

我在哪里遗漏了问题?

感谢您的帮助。

【问题讨论】:

您使用的是什么关系型数据库?您能否举例说明预期的结果是什么? 为什么在 TranHeader 上使用左连接?确认一下,您的问题是 TranHeder 中的多条记录与在 Trandetail 中找到的一条记录相匹配? Vache - MSSQL 2008 - 我将更新关于结果集的问题。 HLGEM,问题是我从 TranDetail 得到重复。一个客户端可能有多个标头交易,无论该数字是多少,交易细节记录都会乘以它。 也许你想要UNION而不是UNION ALL 【参考方案1】:

在获取数据时使用 distinct

SELECT  distinct
b.ClientName,
a.TranID,
a.TranRemark1,
a.TranDateOfService,
a.TranPayment   
FROM`enter code here`
(select TranRemark1, TranID from TranDetail
union all
select TranRemark2, TranID from TranDetail
union all
select TranRemark3, TranID from TranDetail) AS a
LEFT JOIN TranHeader AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;

【讨论】:

嗨Peeyush,欢迎来到SO。很好的答案,为了改进它,也许您可​​以提供更多详细信息来说明您的答案为何正确并帮助原始问题的作者?【参考方案2】:

如果执行 UNION ALL,则在 OUTER SQL 上执行 SELECT DISTINCT。 如果执行 UNION,它将处理重复项。

虽然我相信带有 DISTINCT 的 UNION ALL 提供了更好的性能....

【讨论】:

【参考方案3】:

你可以尝试替换吗:

LEFT JOIN TranHeader AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;

与:

LEFT JOIN
  ( SELECT DISTINCT
        TranId, ClientName
    FROM TranHeader
  ) AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;

【讨论】:

是的,添加 DISTINCT 似乎可以解决这个问题。谢谢。以下内容也将起作用:SELECT DISTINCT b.ClientName、a.TranID、a.TranRemark1、a.TranDateOfService、a.TranPayment FROM(选择 TranRemark1、TranID from TranDetail union all select TranRemark2、TranID from TranDetail union all select TranRemark3、TranID from TranDetail) AS a LEFT JOIN TranHeader AS b ON b.TranID = a.TranID WHERE a.TranRemark1 = @RemarkCode;【参考方案4】:

怎么样

SELECT
  b.ClientName,
  a.TranID,
  a.TranRemark1,
  a.TranDateOfService,
  a.TranPayment
WHERE a.TranRemark1 = @RemarkID JOIN TranHeader b ON b.TranID = a.TranID
UNION ALL
SELECT
  b.ClientName,
  a.TranID
  a.TranRemark2,
  a.TranDateOfService,
  a.TranPayment
WHERE a.TranRemark2 = @RemarkID JOIN TranHeader b ON b.TranID = a.TranID
UNION ALL
SELECT
  b.ClientName,
  a.TranID,
  a.TranRemark3,
  a.TranDateOfService,
  a.TranPayment
WHERE a.TranRemark3 = @RemarkID JOIN TranHeader b ON b.TranID = a.TranID

?

我最初是建议的

SELECT  
b.ClientName,
a.TranID,
a.TranRemark1,
a.TranDateOfService,
a.TranPayment,
a.TranRemark1,
a.TranRemark2,
a.TranRemark3   
FROM
TranDetail a JOIN TranHeader As b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode 
  OR a.TranRemark2 = @RemarkCode 
  OR a.TranRemark3 = @RemarkCode;

但您认为您可能希望每条评论单独一行?

【讨论】:

Nathan - 我尝试了您的第一个选项,得到的结果与我的初始查询相同 - 详细记录乘以标题记录的数量。重新选择第二个选项,是的,我希望结果集被“标准化”,即每个备注都有一个单独的行。

以上是关于一起使用 SQL JOIN 和 UNION的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 使用 Union All 和 Join 计算

SQL Select - Union 结合 Join 查询导致错误

2-2spark的union和join操作演示

SQL中的Join和UNION有啥区别

SQL 里LEFT JOIN 和UNION 怎么一同使用?

sql中union 和 union all的区别