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 ALL
。 UNION
默认禁止重复
【讨论】:
【参考方案3】:UNION
将消除重复的行,无论它们是在两个结果集之间还是在你的情况下,在一个结果集中。尝试改用UNION ALL
。
【讨论】:
感谢您的快速回复。是的,它奏效了。是的,第二组不应该返回任何这些结果,这就是为什么我对它为什么会干扰感到困惑,没有意识到联合抑制的结果。 该死,我知道联合删除重复项,但认为它是在结果集之间。从来不知道它可以在 1 个结果集中。这改变了事情。 ....***偷偷去修复一些关于生产的查询....***以上是关于SQL 在使用 UNION 时返回的结果较少?的主要内容,如果未能解决你的问题,请参考以下文章