在没有UNION的情况下获取两个数据集的结果

时间:2019-06-05 00:45:10

标签: sql-server union openquery

我正在编写一个存储过程,以从Microsoft Great Plains中检索购买,以便可以对其进行处理。

大平原地区有两套发票表格。 SOP10100 / SOP10200包含发票抬头和尚未过帐的发票的详细信息。 SOP30200 / SOP30300包含发票抬头和已过帐发票的详细信息。购买产品后,它将立即进入SOP10100 / SOP10200,并在发布后将其从SOP10100 / SOP10200移至SOP30200 / SOP30300。有一个公用表SOP10106,其中包含用户定义的字段,并且可以连接到任一表集。

在进行采购时,我们需要检查两个表,以防发票过帐,然后才能对其进行处理。到目前为止,我们能够实现这一目标的唯一方法是通过UNION,这基本上是两个相同的查询,不同之处在于一个查询连接到SOP10100 / SOP10200,另一个连接到SOP30200 / SOP30300。

我希望找到一种方法可以将其简化为单个查询(利用共享的SOP10106表),以期获得一个仅包含具有SOP10100 / SOP10200或SOP30200 / SOP30300记录的结果集记录。 GP表的联接在OPENQUERY函数中。

SPROC如下:

SELECT [Account1].AccountID, [Account1].AccountNumber AS 'Order_OrgID', [Account2].AccountNumber AS 'CI_OrgID', [Contact].cncy_CustomerNumber AS 'CustomerID', [Contact].EMailAddress1 AS 'Email', [Contact].FirstName, [Contact].LastName, [StringMapMarket].Value AS 'Market', 
GP.Invoice, GP.SKU, MAP.Name, GP.OrderDate, GP.Quantity, GP.SLPRSNID, RTRIM(GP.SKU) + '-' + [StringMapMarket].Value COLLATE DATABASE_DEFAULT as AdjSku, MAP.CourseID, MAP.SubscriptionID
FROM OPENQUERY(GPSERVER, 'SELECT [SOP10100].SOPNUMBE AS Invoice, [SOP10200].ITEMNMBR AS SKU, [SOP10200].ITEMDESC AS Product, [SOP10100].CREATDDT AS OrderDate, [SOP10200].QTYORDER AS Quantity,
               [SOP10100].SLPRSNID, [SOP10100].CUSTNMBR, [SOP10106].USERDEF1, [SOP10100].SOPTYPE, [SOP10100].VOIDSTTS
               FROM CPI.dbo.SOP10100 WITH (NOLOCK)
               INNER JOIN CPI.dbo.SOP10200 WITH (NOLOCK)  ON [SOP10100].SOPNUMBE = [SOP10200].SOPNUMBE AND [SOP10100].CREATDDT > DATEADD(ww,-4,GETDATE())
               INNER JOIN CPI.dbo.SOP10106 WITH (NOLOCK)  ON [SOP10100].SOPNUMBE = [SOP10106].SOPNUMBE WHERE [SOP10200].SOPTYPE = 3
               AND [SOP10100].VOIDSTTS <> 1
               AND NOT [SOP10106].USERDEF1 = ''INTERNAL LMS''') as GP
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account1] WITH(NOLOCK) ON GP.CUSTNMBR = [Account1].AccountNumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Contact WITH(NOLOCK) ON GP.USERDEF1 = [Contact].cncy_customernumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account2] WITH(NOLOCK) ON [Contact].ParentCustomerId = [Account2].Id
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapMarket] WITH(NOLOCK) ON [Account1].cncy_MarketType = [StringMapMarket].AttributeValue AND [StringMapMarket].AttributeName = 'cncy_MarketType' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapCountry] WITH(NOLOCK) ON [Contact].cncy_address1country = [StringMapCountry].AttributeValue AND [StringMapCountry].AttributeName = 'cncy_address1country' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.vwLmsMapping AS MAP WITH(NOLOCK) ON MAP.Subscription = 'true' AND 
                    CASE 
                        WHEN [StringMapCountry].Value IN ('US','Canada') THEN RTRIM(GP.SKU) + '-' + 
                            CASE
                               WHEN [StringMapMarket].Value IN ('HE','MH') THEN 'HE'
                               WHEN [StringMapMarket].Value IN ('ED') THEN 'ED'
                               ELSE 'HS'
                            END
                        ELSE RTRIM(GP.SKU) 
                    END = map.SKU
LEFT OUTER JOIN SeatLog WITH(NOLOCK) ON GP.Invoice = [SeatLog].Invoice AND RTRIM(GP.SKU) = [SeatLog].SKU
WHERE GP.SOPTYPE = 3
AND GP.VOIDSTTS <> 1
AND NOT GP.USERDEF1 = 'INTERNAL LMS'
AND [SubscriptionLog].ID IS NULL

UNION

SELECT [Account1].AccountID, [Account1].AccountNumber AS 'Order_OrgID', [Account2].AccountNumber AS 'CI_OrgID', [Contact].cncy_CustomerNumber AS 'CustomerID', [Contact].EMailAddress1 AS 'Email', [Contact].FirstName, [Contact].LastName, [StringMapMarket].Value AS 'Market', 
GP.Invoice, GP.SKU, MAP.Name, GP.OrderDate, GP.Quantity, GP.SLPRSNID, RTRIM(GP.SKU) + '-' + [StringMapMarket].Value COLLATE DATABASE_DEFAULT as AdjSku, MAP.CourseID, MAP.SubscriptionID
FROM OPENQUERY(GPSERVER, 'SELECT [SOP30200].SOPNUMBE AS Invoice, [SOP30300].ITEMNMBR AS SKU, [SOP30300].ITEMDESC AS Product, [SOP30200].CREATDDT AS OrderDate, [SOP30300].QTYORDER AS Quantity,
               [SOP30200].SLPRSNID, [SOP30200].CUSTNMBR, [SOP10106].USERDEF1, [SOP30200].SOPTYPE, [SOP30200].VOIDSTTS
               FROM CPI.dbo.SOP30200 WITH (NOLOCK)
               INNER JOIN CPI.dbo.SOP30300 WITH (NOLOCK)  ON [SOP30200].SOPNUMBE = [SOP30300].SOPNUMBE AND [SOP30200].CREATDDT > DATEADD(ww,-4,GETDATE())
               INNER JOIN CPI.dbo.SOP10106 WITH (NOLOCK)  ON [SOP30200].SOPNUMBE = [SOP10106].SOPNUMBE WHERE [SOP30300].SOPTYPE = 3
               AND [SOP30200].VOIDSTTS <> 1
               AND NOT [SOP10106].USERDEF1 = ''INTERNAL LMS''') as GP
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account1] WITH(NOLOCK) ON GP.CUSTNMBR = [Account1].AccountNumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Contact WITH(NOLOCK) ON GP.USERDEF1 = [Contact].cncy_customernumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account2] WITH(NOLOCK) ON [Contact].ParentCustomerId = [Account2].Id
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapMarket] WITH(NOLOCK) ON [Account1].cncy_MarketType = [StringMapMarket].AttributeValue AND [StringMapMarket].AttributeName = 'cncy_MarketType' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapCountry] WITH(NOLOCK) ON [Contact].cncy_address1country = [StringMapCountry].AttributeValue AND [StringMapCountry].AttributeName = 'cncy_address1country' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.vwLmsMapping AS MAP WITH(NOLOCK) ON MAP.Subscription = 'true' AND 
                    CASE 
                        WHEN [StringMapCountry].Value IN ('US','Canada') THEN RTRIM(GP.SKU) + '-' + 
                            CASE
                               WHEN [StringMapMarket].Value IN ('HE','MH') THEN 'HE'
                               WHEN [StringMapMarket].Value IN ('ED') THEN 'ED'
                               ELSE 'HS'
                            END
                        ELSE RTRIM(GP.SKU) 
                    END = map.SKU
LEFT OUTER JOIN SeatLog WITH(NOLOCK) ON GP.Invoice = [SeatLog].Invoice AND RTRIM(GP.SKU) = [SeatLog].SKU
WHERE GP.SOPTYPE = 3
AND GP.VOIDSTTS <> 1
AND NOT GP.USERDEF1 = 'INTERNAL LMS'
AND [SubscriptionLog].ID IS NULL

有人知道任何无需使用UNION即可简化此操作的想法吗?我希望提高性能。

1 个答案:

答案 0 :(得分:0)

我试图通过以下方式使用FULL JOIN和COALESCE来做另一种方式:

SELECT COALESCE(Table1.SOPNUMBE, Table2.SOPNUMBE) AS 'SOPNUMBE', COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR) AS 'SKU', COALESCE(Table1.CUSTNMBR, Table2.CUSTNMBR) AS 'Account_Number', [SubscriptionLog].ID
FROM (SELECT SOP10100.SOPNUMBE,SOP10200.ITEMNMBR,SOP10100.CUSTNMBR FROM [GPSERVER].CPI.dbo.SOP10100 INNER JOIN [GPSERVER].CPI.dbo.SOP10200 ON SOP10100.SOPNUMBE = SOP10200.SOPNUMBE) AS Table1
FULL JOIN (SELECT SOP30200.SOPNUMBE,SOP30300.ITEMNMBR,SOP30200.CUSTNMBR FROM [GPSERVER].CPI.dbo.SOP30200 INNER JOIN [GPSERVER].CPI.dbo.SOP30300 ON SOP30200.SOPNUMBE = SOP30300.SOPNUMBE) AS Table2 ON Table1.SOPNUMBE = Table2.SOPNUMBE AND Table1.ITEMNMBR = Table2.ITEMNMBR AND Table1.CUSTNMBR = Table2.CUSTNMBR
INNER JOIN [GPSERVER].CPI.dbo.SOP10106 WITH(NOLOCK) ON COALESCE(Table1.SOPNUMBE, Table2.SOPNUMBE) = SOP10106.SOPNUMBE
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account1] WITH(NOLOCK) ON COALESCE(Table1.CUSTNMBR, Table2.CUSTNMBR) = [Account1].AccountNumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Contact WITH(NOLOCK) ON SOP10106.USERDEF1 = [Contact].cncy_customernumber COLLATE DATABASE_DEFAULT
--INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account2] WITH(NOLOCK) ON [Contact].ParentCustomerId = [Account2].Id
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapMarket] WITH(NOLOCK) ON [Account1].cncy_MarketType = [StringMapMarket].AttributeValue AND [StringMapMarket].AttributeName = 'cncy_MarketType' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapCountry] WITH(NOLOCK) ON [Contact].cncy_address1country = [StringMapCountry].AttributeValue AND [StringMapCountry].AttributeName = 'cncy_address1country' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.vwLmsMapping AS MAP WITH(NOLOCK) ON MAP.Subscription = 'true' AND 
                        CASE 
                            WHEN [StringMapCountry].Value IN ('US','Canada') THEN RTRIM(COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR)) + '-' + 
                                CASE
                                   WHEN [StringMapMarket].Value IN ('HE','MH') THEN 'HE'
                                   WHEN [StringMapMarket].Value IN ('ED') THEN 'ED'
                                   ELSE 'HS'
                                END
                            ELSE RTRIM(COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR)) 
                        END = map.SKU
LEFT OUTER JOIN [SubscriptionLog] WITH(NOLOCK) ON SOP10106.SOPNUMBE = [SubscriptionLog].Invoice AND RTRIM(COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR)) = [SubscriptionLog].SKU
WHERE [SubscriptionLog].ID IS NULL

运行起来似乎更好一些,但是它返回重复项,而不是我期望的结果。