SQL 在使用 UNION 时返回的结果较少?

Posted

技术标签:

【中文标题】SQL 在使用 UNION 时返回的结果较少?【英文标题】:SQL returns less results when using UNION? 【发布时间】:2011-11-09 10:03:44 【问题描述】:

我有一个 SQL Server 存储过程,当我添加并集和后半部分时,它没有给出所有结果。前半部分会给我全部 6 个结果,使用并集,我只得到 5 个。

有 3 名患者有自己的 [图表编号],每人有 2 项应显示。如果患者的两个条目的 [CPTCode] 相同,则当我添加联合时,仅显示两个条目中的一个(它给了我所有 6 个具有相同 [cptcode] 而没有联合的条目)。后半部分实际上并没有从我现在正在做的事情中提取任何信息,但它是必要的。

select      /*Patients with chart numbers*/
   B1.[chart Number],
   '0' as newPatient, 
   isnull(Lytec.[Last Name],'') as [Last Name], 
   isnull(Lytec.[First Name],'') as [First Name],
   isnull(Address.[Name],
   Lytec.[Facility Code]) as [Facility], 
   isnull(B1.DOS,'') as [DOS], 
   isnull(Ins.[Name],
   Lytec.[Primary Code]) as [Primary Code],
   isnull(B1.[CPTCode],'') as cptCode, 
   isnull(B1.[Units],'') as [Units], 
   isnull(B1.[Modifiers],'') as [Modifiers], 
   isnull(B1.[cptCodeOther],'') as [cptCodeOther],
   isnull(B1.[cptCode2],'') as cptCode2, 
   isnull(B1.[Units],'') as [Units2], 
   isnull(B1.[Modifiers2],'') as [Modifiers2], 
   isnull(B1.[cptCodeOther2],'') as [cptCodeOther2],
   'name' as ProviderName
from 
   [sandboxmr].dbo.patient Lytec
   left join [dbo].[Billing] B1 on B1.[Chart Number] = Lytec.[Chart Number]
   left join [sandboxmr].dbo.[Address] Address on Lytec.[Facility Code] = Address.[Code]
   left join [sandboxmr].dbo.[Insurance] Ins on Lytec.[Primary Code] = Ins.[Code]
where 
   b1.[userid] = 54
   and (b1.[DateSubmitted] >= convert(varchar(25),'2011-8-31',101) 
   and b1.[DateSubmitted] <= convert(varchar(25),'2011-9-22',101))

union

select      /*Patients without chart numbers*/
   cast(P.id as varchar(15)) as [chart number], 
   '1' as newPatient,  
   isnull(P.[Last Name],'') as [Last Name], 
   isnull(P.[First Name],'') as [First Name],
   isnull(Address.[Name],
   P.[Facility Code]) as [Facility], 
   isnull(IV.DOS,isnull(SV.DOS,'')) as [DOS], 
   isnull(Ins.[Name],P.[Primary_Code]) as [Primary Code],
   isnull(IV.[cptCode],isnull(SV.[cptCode],'')) as cptCode, 
   isnull(IV.[Units],isnull(SV.[Units],'')) as [Units], 
   isnull(IV.[Modifiers],isnull(SV.[Modifiers],'')) as [Modifiers],    
   isnull(IV.[cptcodeother],isnull(SV.[cptcodeother],'')) as [cptCodeOther],
   isnull(IV.[cptCode2],isnull(SV.[cptCode2],'')) as cptCode2, 
   isnull(IV.Units2,isnull(SV.Units2,'')) as [Units2], 
   isnull(IV.[Modifiers2],isnull(SV.[Modifiers2],'')) as [Modifiers2], 
   isnull(IV.[cptCodeOther2],isnull(SV.[cptCodeOther2],'')) as [cptCodeOther2],
   'Name' as ProviderName
from 
   [DNSList].[dbo].[Patient] P 
   left join [dbo].[InitialVisits] IV on p.emr_id = IV.patientid
   left join [dbo].[SubsequentVisits] SV on p.emr_id = SV.patientid
   left join [sandboxmr].dbo.[Address] Address on P.[Facility Code] = Address.[Code]
left join [sandboxmr].dbo.[Insurance] Ins on P.[Primary_Code] = Ins.[Code]
where 
   p.[userid] = 54 
   and p.[Chart Number] is null
   and (p.[DateSubmitted] >= convert(varchar(25),'2011-8-31',101) 
   and p.[DateSubmitted] <= convert(varchar(25),'2011-9-22',101))
order by 
   [Last Name]

为什么会这样,我该如何解决?我尝试在 [cptcode] 区域添加distinct,但它当然会产生错误。

感谢您提供的任何帮助!

【问题讨论】:

您打算使用UNION(不重复)还是UNION ALL(允许两个查询之间重复)? 【参考方案1】:

这里有一点背景。从技术上讲,表格是一组。这是数学意义上的集合。

数学集的两个重要属性是:

一个集合是无序的 集合没有重复项

第一点是为什么行顺序不可靠,除非您添加ORDER BY 子句。第二个原因是您应该始终拥有一个主键以确保每一行确实是不同的。

UNION 操作是一个集合操作,并且 (a) 组合两个集合,(b) 产生一个集合。为了保持集合的完整性,UNION 将删除重复的行。

不幸的是,没有真正的方法可以保证两行是否应该相同,因此 SQL 将简单地比较 SELECT 子句中的值。如果这些值相同,则 SQL 确定存在重复。

这可能导致一个夸张的例子:

SELECT state FROM customers
UNION
SELECT state FROM customers;

原则上,state 值会产生两次,重复值会被删除,而您所拥有的是一种冗长的说法 SELECT DISTINCT

集合行为也是为什么您不能在 SELECT 语句中包含 ORDER BY 子句的原因:一旦您订购了一个数据集,它就不再是一个真实的集合。

(是的,您可以有一个ORDER BY 子句,但它不附加到SELECT 语句,而是附加到生成的UNION)。

当然,SQL 不仅仅是纯粹的数学,所以它包含两个打破集合的特性:

您可以订购带有ORDER BY 子句的套装。

但是,你只能在剩下的工作完成后才能这样做,这就是为什么它是最后一个子句。

您可以使用UNION ALL 子句包含重复项。

【讨论】:

【参考方案2】:

我相信你需要使用UNION ALLUNION 默认禁止重复

【讨论】:

【参考方案3】:

UNION 将消除重复的行,无论它们是在两个结果集之间还是在你的情况下,在一个结果集中。尝试改用UNION ALL

【讨论】:

感谢您的快速回复。是的,它奏效了。是的,第二组不应该返回任何这些结果,这就是为什么我对它为什么会干扰感到困惑,没有意识到联合抑制的结果。 该死,我知道联合删除重复项,但认为它是在结果集之间。从来不知道它可以在 1 个结果集中。这改变了事情。 ....***偷偷去修复一些关于生产的查询....***

以上是关于SQL 在使用 UNION 时返回的结果较少?的主要内容,如果未能解决你的问题,请参考以下文章

SQL injection : UNION attacks

SQL学习之组合查询(UNION)

SQL 中 or 和union的区别连系是啥啊??

组合查询

Union链接查询

SQL语句中:UNION与UNION ALL的区别