Получить результаты двух наборов данных без объединения - PullRequest
0 голосов
/ 05 июня 2019

Я пишу хранимую процедуру для извлечения покупок из Microsoft Great Plains, чтобы их можно было обрабатывать.

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 голосов
/ 05 июня 2019

Я попытался сделать это по-другому, используя 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

Кажется, он работает немного лучше, но возвращает дубликаты, а не ожидаемые результаты.

...