2013-05-27 37 views
1

此视图正常。它在一份报告建筑物向导谈论一个SQLServer 2008 R2选择使用UNION returing duplicates

CREATE view vwQry_LicencePayments 
as 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN 
from 
rptPayment P 
inner join vwQry_xhsEntity_Base E on P.HolderHistoryID = E.HistoryID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 

union ALL 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN 
from 
(select * from rptPayment where HolderHistoryID is null) P 
inner join vwQry_Entity E on P.HolderID = E.EntityID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 

一个要求,包括支付日期(LP.dateTimeStamp)使用了上来。因此,添加额外字段(LP.dateTimeStamp)和两个联接(licenceFeePayment tble和licencePayment tble)必然会在结果集中造成重复。我假设,例如,如果已经通过三次独立付款支付了许可证,它将在licencefeePayment表中有三个记录。他们改变我做的是:

CREATE view vwQry_LicencePayments 
as 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN, LP.DatetimeStamp AS DatetimeStamp 
from 
rptPayment P 
inner join vwQry_xhsEntity_Base E on P.HolderHistoryID = E.HistoryID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 
     inner join licenceFeePayment LFP on P.licenceID = LFP.licenceID 
     inner join licencePayment LP on LFP.paymentID = LP.paymentID 

union ALL 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN, LP.DatetimeStamp AS DatetimeStamp 
from 
(select * from rptPayment where HolderHistoryID is null) P 
inner join vwQry_Entity E on P.HolderID = E.EntityID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 
     inner join licenceFeePayment LFP on P.licenceID = LFP.licenceID 
     inner join licencePayment LP on LFP.paymentID = LP.paymentID 

帮助将非常感激。我如何加入这两张表并避免重复?

正如@注册用户指出的,虽然我已经这样做了,但并不像从我的UNION中删除ALL那么简单。

@注册用户感谢您的回复。我根据你的帮助对查询进行了更改,现在又有了一个小问题。我添加了一个来自'paymentType'表的名为'PaymentTypeDesc'的字段。由于此表通过“LicencePayment”加入,因此我必须将其置于您的子查询中。我仍然得到一些重复,因为我现在认为,不仅可以多次付款的许可证,他们可以来自多个不同的来源EG EFTPOS,现金等...

我怎样才能迎合不仅多个支付交易还有多种付款方式?这是我改变工作查询中使用你的帮助后:

CREATE view vwQry_LicencePaymentsNew 
as 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN 
    , lic.VehicleRegNo as VehicleRegNo 
    , payment.PaymentTypeDesc as PaymentTypeDesc 
    , S.StatusTypeDesc as StatusTypeDesc 
    , Payment.LastPaymentDate as DatetimeStamp 
    -- , Payment.FirstPaymentDate 
from 
rptPayment P 
inner join vwQry_xhsEntity_Base E on P.HolderHistoryID = E.HistoryID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 
inner join licence Lic on P.licenceID = lic.licenceID 
inner join vwLicCurrentStatus S on P.LicenceID=S.LicenceID 
inner join 
    (SELECT LFP.licenceID 
     , FirstPaymentDate = MIN(LP.DatetimeStamp) 
     , LastPaymentDate = MAX(LP.DatetimeStamp) 
     , PType.PaymentTypeDesc 
    FROM licenceFeePayment LFP 
    INNER JOIN licencePayment LP 
     on LFP.paymentID = LP.paymentID 
    INNER JOIN paymentType PType 
     on LP.paymentTypeID = PType.paymentTypeID 
    GROUP BY lfp.licenceID, PType.PaymentTypeDesc) Payment 
    ON P.licenceID = Payment.licenceID 

union 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN 
    , lic.VehicleRegNo as VehicleRegNo 
    , payment.PaymentTypeDesc as PaymentTypeDesc 
    , S.StatusTypeDesc as StatusTypeDesc 
    , Payment.LastPaymentDate as DatetimeStamp 
    -- , Payment.FirstPaymentDate 

from rptPayment P 
inner join vwQry_xhsEntity_Base E on P.HolderHistoryID = E.HistoryID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 
inner join licence Lic on P.licenceID = lic.licenceID 
inner join vwLicCurrentStatus S on P.LicenceID=S.LicenceID 
inner join 
    (SELECT LFP.licenceID 
     , FirstPaymentDate = MIN(LP.DatetimeStamp) 
     , LastPaymentDate = MAX(LP.DatetimeStamp) 
     , PType.PaymentTypeDesc 
    FROM licenceFeePayment LFP 
    INNER JOIN licencePayment LP 
     on LFP.paymentID = LP.paymentID 
    INNER JOIN paymentType PType 
     on LP.paymentTypeID = PType.paymentTypeID 

    GROUP BY lfp.licenceID, PType.PaymentTypeDesc) Payment 
    ON P.licenceID = Payment.licenceID 
+0

从您的'UNION'语句中删除'ALL'。 –

+0

@Ken谢谢你的时间。我已添加到我的帖子,仍然有一个问题,我会帮忙。正如注册用户指出的那样,并不像删除所有的那样简单。 – Mat41

+0

然后您需要提供更多信息(如某些示例数据和您希望从该数据获得的输出)。没有它,我们只能猜测问题可能是什么,而这不是StackOverflow的工作原理。 –

回答

1

看看您需要首先解决的基本业务问题是确定要如何呈现这些数据给最终用户。在LastPaymentDate的情况下,您基本上决定最后一个DatetimeStamp是获胜记录。该记录是通过使用最简单的方法挑选的:子查询中列的最大值。如果您有多种付款类型说明,付款来源或其他付款方式属性,则您需要选择一个赢家或将这些值汇总在一起。这使你有几种选择:

  1. 如果你只是想在最后一次付款的属性,那么您可以使用ROW_NUMBER()聚集窗口函数,然后限制你的加入到数据到最后一行。对于真正的大型数据集,这可能会很昂贵,但是您可以在事务性系统本身或通用ETL过程中的部分数据集中分配值。如果数据集相对较小,那么成本可能微不足道。

  2. 如果每个表中存在可靠的上次修改日期,则可以运行子查询以将最大修改日期和过滤器返回到符合此条件的行。如果多行具有相同的最后修改日期,则此方法也可能执行得不好,并且可能无法正常工作,那么您仍可能会返回多行。

  3. 您可以将所有选定的付款方式,来源或其他属性连接到一个字段中。这通常是一个糟糕的解决方案,因为用户可能需要将这些值分离出来,但在某些情况下,这恰恰是正确的解决方案。您需要让业务所有者确定这是否是正确的解决方案。

  4. 您可以与请求这些数据的企业所有者交谈,并解释数据是如何工作的以及如何为他们提供数据的可能排列组合。有些用户可能需要最后的付款属性,有些可能需要连接数据,有些用户可能需要全部历史记录,这意味着您可能需要提供单独的非汇总付款详细信息报告。我建议在做出假设前,与利益相关方一起审查,编码解决方案,并找出需要重新编码整个解决方案,因为它不符合业务需求。

原始响应BELOW

如果LicensePayment表包括多个不同的值,则改变UNION ALL到UNION将是不够的。您需要决定此表是否需要在单独的字段中获取第一个付款日期,最后付款日期或两者。您可以通过以下方式完成此操作:(1)将联合转换为LicensePayment表转换为子查询,或(2)分别汇总LicensePayment数据并加入汇总表。以下是使用第一种方法的示例查询:

CREATE view vwQry_LicencePayments 
as 

select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN 
    , Payment.FirstPaymentDate 
    , Payment.LastPaymentDate 
from 
rptPayment P 
inner join vwQry_xhsEntity_Base E on P.HolderHistoryID = E.HistoryID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 
inner join 
    (SELECT LFP.LicenseID 
     , FirstPaymentDate = MIN(LP.DatetimeStamp) 
     , LastPaymentDate = MAX(LP.DatetimeStamp) 
    FROM licenceFeePayment LFP 
    INNER JOIN licencePayment LP 
     on LFP.paymentID = LP.paymentID 
    GROUP BY lfp.LicenseID) Payment 
    ON P.licenceID = Payment.licenceID 
union ALL 
select 
P.*, 
LT.LicenceTypeDesc, FT.FeeTypeDesc, FT.ThroughputText, FT.Prorata as IsProrata, PT.PaymentStatusDesc, PT.IsPaid, 
E.EntityType as HolderEntityType, E.EntityTypeDesc as HolderEntityTypeDesc, E.PersonTitle, E.PersonFirstname, E.PersonSurname, 
E.OrganisationName, E.FullName as HolderFullName, 
E.MailAddress as HolderMailAddress, E.Suburb as HolderSuburb, E.State as HolderState, E.Postcode as HolderPostcode, 
E.Mobile as HolderMobile, E.Email, E.PFN as HolderPFN 
    , Payment.FirstPaymentDate 
    , Payment.LastPaymentDate 
from rptPayment P 
inner join vwQry_Entity E on P.HolderID = E.EntityID 
inner join LicenceType LT on P.LicenceTypeID=LT.LicenceTypeID 
inner join LicenceFeeType FT on P.FeeTypeID=FT.FeeTypeID 
inner join PaymentStatusType PT on P.PaymentStatusID = PT.PaymentStatusID 
inner join 
    (SELECT lfp.LicenseID 
     , FirstPaymentDate = MIN(LP.DatetimeStamp) 
     , LastPaymentDate = MAX(LP.DatetimeStamp) 
    FROM licenceFeePayment LFP 
    INNER JOIN licencePayment LP 
     on LFP.paymentID = LP.paymentID 
    GROUP BY lfp.LicenseID) Payment 
    ON P.licenceID = Payment.licenceID 
WHERE p.HolderHistoryID is null; 
0

肯指出,你必须使用UNION,不UNION ALL

What is the difference between UNION and UNION ALL?

+0

如果LP.DatetimeStamp在付款之间有所不同 - 如果该字段表示不同的付款日期,这可能是不合适的。 –

+0

是的,这是正确的dateTimeStamp将是不同的.. – Mat41