How do I modify a Stored Procedure to Join an additional table? - join

I have a fairly complex Stored Procedure that is joining several tables together, but I need yet another column called in from a table that is yet to be joined.
Here's the Stored Procedure as it stands:
CREATE PROCEDURE [rpt].[PlannerShipToLocations_ds1]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql nvarchar(4000)
,#DateStart nvarchar(10) = '2015-01-01'
DECLARE #t TABLE (
[PCN] int
,[Part_Key] int
,[Customer_Address_No] int
PRIMARY KEY CLUSTERED (
[Part_Key]
,[Customer_Address_No]
,[PCN]
)
)
SET #sql =
'SELECT *
FROM OPENQUERY (PLEXRPTSVR,
''SELECT DISTINCT
s.[PCN]
,sl.[Part_Key]
,s.[Customer_Address_No]
FROM [Sales_v_Shipper_e] AS s
INNER JOIN [Sales_v_Shipper_Status_e] AS ss
ON s.[PCN] = ss.[PCN]
AND s.[Shipper_Status_Key] = ss.[Shipper_Status_Key]
INNER JOIN [Sales_v_Shipper_Line_e] AS sl
ON s.[PCN] = sl.[PCN]
AND s.[Shipper_Key] = sl.[Shipper_Key]
WHERE 1 = 1
AND ss.[Shipped] = 1
AND s.[Ship_Date] >= ''''' + #DateStart + '''''
;'')'
INSERT INTO #t
EXECUTE sp_executesql #sql
;WITH base AS (
SELECT DISTINCT u.[Last_Name] + ', ' + u.[First_Name] AS [Planner]
,c.[Customer_Code] AS [Customer Code]
,c.[Name] AS [Customer Name]
,a.[Customer_Address_Code] AS [Customer Address Code]
**/* xxx.[Country] AS [Country] */**
FROM [plx].[Part_v_Customer_Part_e] cp
INNER JOIN [plx].[Part_v_Part_e] p
ON cp.[Plexus_Customer_No] = p.[Plexus_Customer_No]
AND cp.[Part_Key] = p.[Part_Key]
INNER JOIN [plx].[Common_v_Customer_e] c
ON cp.[Plexus_Customer_No] = c.[Plexus_Customer_No]
AND cp.[Customer_No] = c.[Customer_No]
INNER JOIN [plx].[Plexus_Control_v_Plexus_User_e] u
ON p.[Plexus_Customer_No] = u.[Plexus_Customer_No]
AND p.[Planner] = u.[Plexus_User_No]
OUTER APPLY (
SELECT [Customer_Address_Code], **/*[Country]*/**
FROM [plx].[Common_v_Customer_Address_e] a
INNER JOIN #t t
ON a.[Plexus_Customer_No] = t.[PCN]
AND a.[Customer_Address_No] = t.[Customer_Address_No]
**/* INNER JOIN [plx].[Common_v_Country] xxx
ON a.[Country_Key] = xxx.[Country_Key] */**
WHERE a.[Plexus_Customer_No] = p.[Plexus_Customer_No]
AND a.[Customer_No] = c.[Customer_No]
AND t.[Part_Key] = p.[Part_Key]
AND a.[Ship_To] = 1
) a
**
/* INNER JOIN [plx].[Common_v_Country] xxx
ON a.[Country_Key] = xxx.[Country_Key] */
/*
OUTER APPLY (
SELECT [Country]
FROM [plx].[Common_v_Country] xxx
INNER JOIN #t t
ON a.[Country_Key] = xxx.[Country_Key]
WHERE a.[Plexus_Customer_No] = p.[Plexus_Customer_No]
AND a.[Customer_No] = c.[Customer_No]
AND t.[Part_Key] = p.[Part_Key]
AND a.[Ship_To] = 1
) xxx
*/**
WHERE 1 = 1
AND u.[Lockout] = 0
AND p.[Part_Status] IN ('Production', 'Production - Near EOP', 'Pre-Production')
AND cp.[Active] = 1
)
SELECT t1.[Planner]
,t1.[Customer Code]
,t1.[Customer Name]
,STUFF(
(SELECT
' | ' + t2.[Customer Address Code]
FROM base t2
WHERE t1.[Planner] = t2.[Planner]
and t1.[Customer Code] = t2.[Customer Code]
ORDER BY t2.[Customer Address Code]
FOR XML PATH(''), TYPE
).value('.','varchar(max)')
,1,3,'') AS [Customer Address Code(s)]
FROM base t1
GROUP BY t1.[Planner]
,t1.[Customer Code]
,t1.[Customer Name]
ORDER BY [Customer Code]
,[Planner]
,[Customer Address Code(s)]
END
GO
I've bolded the sections that are my best guesses about how to go about joining this additional table, I recognize that I wouldn't use all of them but I wanted to show my thoughts. To break it down:
1.) [plx].[Common_v_Customer_Address_e] a AND [plx].[Common_v_Country] xxx are the two tables I need in order to call [Country] out by name. I essentially need to add this as a column displayed on the report and eventually will need to sort on it as well (I'll probably add it to ORDER BY at the end).
2.) I'm not sure if I need to be joining [plx].[Common_v_Country] xxx within the OUTER APPLY or if it needs its own separate INNER JOIN or what. I've illustrated and commented out both here. So far everything I've tried results in "The multi-part identifier 'xxx.Country' could not be bound."
Thanks for the help.
I've tried modifying the OUTER APPLY to include the new table. I've tried creating my own new INNER JOIN. I've tried creating my own new OUTER APPLY.

Related

SSRS report: Could not update a list of fields for the query. An item with same key has already been added

I have written a stored procedure as follows:
ALTER PROCEDURE [dbo].[Transaction]
(
#date_start date,
#date_end date
)
AS
BEGIN
with
rntexportbatch as (
Select
fb.BatchId,
rt.TransactionId,
count(*) as line_Count
from CxWarehouse.dbo.FinancialBatchPostingDetail fbpd
INNER JOIN CxWarehouse.dbo.FinancialBatchPosting fb
on (fb.BatchPostingId = fbpd.BatchPostingId and NominalAccount='12000' ) ---and NominalAccount='12000'
INNER JOIN CxWarehouse.dbo.FinancialBatch finb
on (finb.BatchId = fb.BatchId)
INNER JOIN CxWarehouse.dbo.SystemLookup l
on (l.LookupReference = finb.TransactionTypeId and LookupTypeId = 42)
INNER JOIN CxWarehouse.dbo.Financialtransaction ft
on (ft.TransactionId = fbpd.TransactionId)
LEFT JOIN CxWarehouse.dbo.RentTransactionElement rte
on (rte.TransactionElementId = ft.EntityId)
LEFT JOIN CxWarehouse.dbo.RentElement re
ON (re.ElementId = rte.ElementId)
LEFT JOIN CxWarehouse.dbo.RentTransaction rt
ON (rt.TransactionId = rte.TransactionId)
Group by rt.TransactionId,fb.BatchId
)
Select
ast.AssetId,
ast.AssetReference,
ast.[Agreement Description],
ast.CompanyIds,
rntAcc.AccountId,
rntAcc.AccountReference,
rntAcc.PaymentReference,
rt.TransactionId,
rt.AccountId,
rt.TransactionDate,
rt.TransactionTypeId,
[Transaction Type Id Description],
rt.PostingDate,
rt.PeriodNumber,
rt.Description as 'Rent Transaction Description',
rt.Notes,
[ElementId Description] ,
rntPay.BatchReference as 'Import BatchId',
rntPay.[Import Value],
rntexportbatch.BatchId as 'Export BatchId',
final.Value as 'Export Value'
from CxWarehouse.dbo.RentTransaction as rt
LEFT Join (
Select LookupId,
LookupTypeId,
LookupReference,
Description as 'Transaction Type Id Description'
from CxWarehouse.dbo.SystemLookup
where LookupTypeId = 46
) lu
on rt.TransactionTypeId = lu.LookupReference
LEFT Join (
Select
te.TransactionId,
te.TransactionElementId,
te.ElementId,
te.Value,
rntElm.Description as 'ElementId Description'
from CxWarehouse.dbo.RentTransactionElement as te
LEFT Join (
Select * from CxWarehouse.dbo.RentElement
) rntElm
on te.ElementId = rntElm.ElementId
) final
on rt.TransactionId = final.TransactionId
LEFT JOIN (
Select
t.AccountId,
t.AccountReference,
t.PaymentReference,
typ.Description as 'AccountType Description'
from CxWarehouse.dbo.RentAccount as t
left Join CxWarehouse.dbo.RentAccountType as typ
on t.AccountTypeId = typ.AccountTypeId
) rntAcc
on rt.AccountId = rntAcc.AccountId
Left Join (
Select
ast.AssetId,
AssetReference,
rntInf.AccountId,
rntInf.[Agreement Description],
rntInf.CompanyIds
from CxWarehouse.dbo.Asset as ast
left join (
Select
rntAgAs.AgreementAssetId,
rntAgAs.AgreementId,
rntAgAs.AssetId,
rntAgr.AccountId,
rntAgr.[Agreement Description],
rntAgr.CompanyIds
from CxWarehouse.dbo.RentAgreementAsset as rntAgAs
left join (
Select
rntAgmt.AgreementId,
rntAgmt.AgreementReference,
rntAgmt.AgreementTypeId,
rntAgmtTyp.Description as 'Agreement Description',
rntAgmtTyp.CompanyIds,
accEpi.AccountId
from CxWarehouse.dbo.RentAgreement as rntAgmt
LEFT JOIN CxWarehouse.dbo.RentAgreementType rntAgmtTyp
on rntAgmt.AgreementTypeId = rntAgmtTyp.AgreementTypeId
Left Join (
Select
rntAgEp.AgreementEpisodeId,
rntAgEp.AgreementId,
rntAgAc.AccountId
from CxWarehouse.dbo.RentAgreementEpisode as rntAgEp
Left Join CxWarehouse.dbo.RentAgreementAccount as rntAgAc
on rntAgEp.AgreementEpisodeId =rntAgAc.AgreementEpisodeId
) accEpi
on rntAgmt.AgreementId = accEpi.AgreementId
) rntAgr
on rntAgAs.AgreementId = rntAgr.AgreementId
) rntInf
on ast.AssetId = rntInf.AssetId
) ast
on rntAcc.AccountId = ast.AccountId
Left Join (
Select
rp.PaymentId,
rp.BatchReference,
rpd.PaymentDetailId,
rpd.Value as 'Import Value',
GeneratedTransactionId
from CxWarehouse.dbo.RentPayment as rp
left Join CxWarehouse.dbo.RentPaymentDetail rpd
on rp.PaymentId = rpd.PaymentId
left join CxWarehouse.dbo.RentPaymentPosting rpp
on rpd.PaymentDetailId = rpp.PaymentDetailId
) rntPay
on rt.TransactionId = rntPay.GeneratedTransactionId
LEFT JOIN rntexportbatch
on rntexportbatch.TransactionId = rt.TransactionId
where rt.PostingDate between #date_start and #date_end
END
I used that stored procedure in SSRS report. When I clicked on the dataset option of the report and refresh the data set, it gave following error:
I looked at the forum and found that error comes due to two or more columns have same name. I looked at the code and made sure that no column have same name. However, the problem still exist. Could anyone help me where I am making the mistake?
You have two columns both called AccountID being returned from your query
...
rntAcc.AccountId,
rntAcc.AccountReference,
rntAcc.PaymentReference,
rt.TransactionId,
rt.AccountId,
....
Alias or remove one of these columns.

Join subqueries serval times

I have code that run:
How can I join another query in this subqueries?
I whant a third table that joins with the other tables.
How can I achive this?
select *
from
( select irart, fiben1 as "Benämning", fisald +irbant as "disp.saldo", sum(irbant) as "Lev.Best"
from triir00
left join trafi00
on irart = fiart and irfili = fifili
where IRSTYP between 00 and 02 and irlev = '2602688' and irfili = 10 and fihugr = 5
group by irart,fiben1,irlev,fisald,irbant
) as antalLev
full join
( select raart, fiben1 as "Benämning", raorn9 as "Ordernummer", fisald- raanta as "Disp.Saldo", sum(raanta) as "Kund.Best"
from trora00
left outer join trohu00
on huorn9 = raorn9
left join trafi00
on raart = fiart and rafili = fifili
where rastyp <= 02 and rafili <> 0 and raotyp = 1 and ralev1 = '2602688' and fihugr = 5
group by raart,fiben1,raorn9,fisald,raanta
) as antalBest
on antalLev.irart = antalBest.raart
Wrap your original query into brackets:
select *
from
(
-- your original query follows below
select *
from
(
select columns_for_outer_join, other_columns
from ...
) as antalLev
full join
(
select columns_for_outer_join, other_columns
from ...
) as antalBest on antalLev.irart = antalBest.raart
-- end of your original query
) a
join (
-- your another sub-query comes here
select columns_for_outer_join, other_columns
from ...
-- end of your another sub-query
) b on <a.columns_for_outer_join = b.columns_for_outer_join>
...;

How to write procedure with several output parameters?

I have created this procedure but this is throwing error.
CREATE PROCEDURE GetSurrenderPolicyDetails
#policy_Id int,
#name nvarchar(50) output,
#policy_Amount Decimal(10,2) output,
#premiumPaidTillDate Decimal(10,2) output
AS
BEGIN
SET NOCOUNT ON;
SELECT
#name = Policy_Details.Name,
#policy_Amount = Insurance_Policy_Details.Policy_Amount,
#premiumPaidTillDate = SUM(Payment_Premium_Details.Premium_Amount)
FROM
Policy_Details
INNER JOIN
Payment_Premium_Details ON (Policy_Details.Policy_Id = Payment_Premium_Details.Policy_Id)
INNER JOIN
Insurance_Policy_Details ON (Policy_Details.Ins_Id = Insurance_Policy_Details.Ins_Id)
WHERE
Policy_Details.Policy_Id = #policy_Id;
END
GO
The error says
Column 'Policy_Details.Name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Well, the error is pretty clear: you have a SUM() aggregate in your SELECT, so therefore, you need to use GROUP BY for the other columns in your SELECT statement:
SELECT
#name = Policy_Details.Name,
#policy_Amount = Insurance_Policy_Details.Policy_Amount,
#premiumPaidTillDate = SUM(Payment_Premium_Details.Premium_Amount)
FROM
Policy_Details
INNER JOIN
Payment_Premium_Details ON (Policy_Details.Policy_Id = Payment_Premium_Details.Policy_Id)
INNER JOIN
Insurance_Policy_Details ON (Policy_Details.Ins_Id = Insurance_Policy_Details.Ins_Id)
WHERE
Policy_Details.Policy_Id = #policy_Id;
GROUP BY
Policy_Details.Name,
Insurance_Policy_Details.Policy_Amount,
your problem isn't your output parameters, but your join clauses; Instead, try something like:
INNER JOIN Insurance_Policy_Details
ON Policy_Details.Ins_Id = Insurance_Policy_Amount.Ins_Id
INNER JOIN Payment_Premium_Details
ON Policy_Details.Policy_Id = Payment_Premium_Details.Policy_Id

How to simulate Subqueries in the ON Clause in Vertica database?

Hy everbody , i am having some trouble in transforming a query that has a set of subqueries in the ON clause.
The initial code was created in SQL Server and i have changed to work on Vertica.
This is the code :
SELECT
DISTINCT DocFinanceiro.AutoId AS AutoId,
DocFinanceiro.Classe AS ClasseDoc,
EspecPrestador.Seq AS Sequencia,
PrestadorServico.Codigo AS CodigoPrest,
PessoaPrest.Nome AS NomePrestador,
DocFinanceiro.CompFinanceira AS CompFinanceira,
EspecialidadeServico.Nome AS Especialidade,
ClassePrestador.Nome AS ClsPrestador,
RegistroPessoa.Numero AS RegistroINSS,
RegistroPessoa.Tipo AS TipoRegPessoa,
DocFinanceiro.DataVencimento AS DataVencimentoDocFin
FROM DocFinanceiro
INNER JOIN ClasseDocFinanceiro
ON DocFinanceiro.Classe = ClasseDocFinanceiro.Codigo
INNER JOIN ItemFinanceiro ON DocFinanceiro.AutoId = ItemFinanceiro.Documento
INNER JOIN ClasseApropriacaoFinan
ON ItemFinanceiro.ClasseApro = ClasseApropriacaoFinan.Codigo
INNER JOIN ContratoFinanceiro
ON DocFinanceiro.ContratoFinanceiro = ContratoFinanceiro.AutoId
INNER JOIN Pessoa ON ContratoFinanceiro.Pessoa = Pessoa.AutoId
INNER JOIN GeradorItemFinan
ON ItemFinanceiro.AutoId = GeradorItemFinan.ItemFinan
INNER JOIN PrestadorServico
ON ContratoFinanceiro.AutoId = PrestadorServico.ContratoFinanceiro
INNER JOIN Pessoa PessoaPrest ON PrestadorServico.Pessoa = PessoaPrest.AutoId
INNER JOIN TipoValorFinan
ON ClasseApropriacaoFinan.TipoValor = TipoValorFinan.Codigo
INNER JOIN ClasseContratoFinanceiro
ON ContratoFinanceiro.Classe = ClasseContratoFinanceiro.AutoId
INNER JOIN ClassePrestador
ON PrestadorServico.Classe = ClassePrestador.Codigo
LEFT JOIN EspecPrestador
ON EspecPrestador.Prestador = PrestadorServico.AutoId
AND EspecPrestador.Seq = 1
LEFT JOIN EspecialidadeServico
ON EspecialidadeServico.AutoId = EspecPrestador.Especialidade
LEFT JOIN RegistroPessoa ON PessoaPrest.AutoId = RegistroPessoa.Pessoa
--This is the part where i getr stuck
AND
(
RegistroPessoa.AutoId =
(
SELECT
RegistroPessoa.AutoId
FROM RegistroPessoa
WHERE RegistroPessoa.Pessoa = PessoaPrest.Autoid
AND (RegistroPessoa.Tipo = 1 OR RegistroPessoa.Tipo = 1) order by 1 limit 1
)
)
--until here
WHERE (GeradorItemFinan.TipoGerador = 1)
AND (DocFinanceiro.CompFinanceira = 1)
AND (PrestadorServico.AutoId = 1)
AND DocFinanceiro.CompSeq = 1
AND (DocFinanceiro.Numero IS NOT NULL)
AND (DocFinanceiro.Classe <> 1)
ORDER BY AutoId, Sequencia
;
If anybody has any ideas it would be great !!
try replace
RegistroPessoa.AutoId = (SELECT...)
to
RegistroPessoa.AutoId IN (SELECT...)
and use aliases for table short names

Sql Server queries optimization techniques

My Stored Procedure takes a very long time to execute.
Can anyone suggest me what I can do to speed up the stored procedure, apart from using some good practices for writing down the queries.
I've heard about creating indices, but I'm not sure what are they.
Please suggest all the best ways to speed up my queries.
Thanks
CREATE PROCEDURE [dbo].[usp_GetAlternates]
(
#NNumber CHAR(11) ,
#pid INT ,
#pbmid INT
)
AS
BEGIN
TRUNCATE TABLE TempTherapeuticAlt
INSERT INTO TempTherapeuticAlt
SELECT NULL AS MedicationID ,
PR.ePrescribingName AS MedicationName ,
U.Strength AS MedicationStrength ,
FRM.FormName AS MedicationForm ,
PR.DEAClassificationID AS DEASchedule ,
NULL AS NDCNumber
FROM Product PR
JOIN ( SELECT MP.MarketedProductID
FROM table2 TCTSP
JOIN table3 MP ON MP.SpecificProductID = TCTSP.SpecificProductID
JOIN ( SELECT TCTSP.TherapeuticConceptTreeID
FROM table3 MP
JOIN table2 TCTSP ON MP.SpecificProductID = TCTSP.SpecificProductID
JOIN ( SELECT
PR.MarketedProductID
FROM
table4 PA
JOIN Product PR ON PA.ProductID = PR.ProductID
WHERE
PA.NDC11 = #NNumber
) PAPA ON MP.MarketedProductID = PAPA.MarketedProductID
) xxx ON TCTSP.TherapeuticConceptTreeID = xxx.TherapeuticConceptTreeID
) MPI ON PR.MarketedProductID = MPI.MarketedProductID
JOIN ( SELECT P.ProductID ,
O.Strength ,
O.Unit
FROM Product AS P
INNER JOIN table3 AS M ON P.MarketedProductID = M.MarketedProductID
INNER JOIN table5 AS S ON M.SpecificProductID = S.SpecificProductID
LEFT OUTER JOIN table6 AS O ON S.SpecificProductID = O.SpecificProductID
GROUP BY P.ProductID ,
O.Strength ,
O.Unit
) U ON PR.ProductID = U.ProductID
JOIN ( SELECT PA.ProductID ,
S.ScriptFormID ,
F.Code AS NCPDPScriptFormCode ,
S.FormName
FROM table4 AS PA
INNER JOIN table7 AS S ON PA.NCPDPScriptFormCode = S.NCPDPScriptFormCode
INNER JOIN table8 AS F ON S.FormName = F.FormName
GROUP BY PA.ProductID ,
S.ScriptFormID ,
F.Code ,
S.FormName
) FRM ON PR.ProductID = FRM.ProductID
GROUP BY PR.ePrescribingName ,
U.Strength ,
FRM.FormName ,
PR.DEAClassificationID
ORDER BY pr.ePrescribingName
SELECT LL.ProductID AS MedicationID ,
temp.MedicationName ,
temp.MedicationStrength ,
temp.MedicationForm ,
temp.DEASchedule ,
temp.NDCNumber ,
fs.[ReturnFormulary] AS FormularyStatus ,
copay.CopaTier ,
copay.FirstCopayTerm ,
copay.FlatCopayAmount ,
copay.PercentageCopay
FROM TempTherapeuticAlt temp
OUTER APPLY ( SELECT TOP 1
ProductID
FROM Product
WHERE ePrescribingName = temp.MedicationName
) AS LL
OUTER APPLY function1(#pid, LL.ProductID, #pbmid) AS fs
OUTER APPLY function2(LL.ProductID, #pbmid) AS copay
ORDER BY LL.ProductID
TRUNCATE TABLE TempTherapeuticAlt
END
GO
Here are a few:
You should have indexes for every column in a WHERE clause. See
your SQL language for how to do it.
Learn how to EXPLAIN PLAN and see what's slow.
Stored procedure languages are functional, not set based. Use JOIN and don't fall into the (n+1) query/iteration trap.
Understand how using certain functions force you to TABLE SCAN in a WHERE clause.

Resources