Proc SQL not returning any columns. Innerjoin - sql-server

I am trying to gather the information on which store is receiving which SKU along with some other relevant info. The data is in multiple tables so i am trying innerjoin the info. I am using SAS and it runs in SQL Server via passthrough. Below is the query i tried. I have confirmed that || works in the pass through. The issue seems to start in the from statement
connect to odbc (dsn='X' uid='X' pwd='XY');
create table School.TRANS_INFO as SELECT * from connection to odbc
(SELECT Distinct
S.Schd_t AS Schd_Date format MMDDYY10.,
S.otb As Ship_Loc,
W.store_NUMBER AS store,
S.SHP_ID AS SHIP_ID,
W.store_CITY_STATE,
Q.Stat_CD AS Status,
(S.PROD_CD || S.plt_CD) AS SKU,
W.ACCOUNT_TYPE as Location
FROM
SHPMT_DTL S
INNER JOIN store W ON W.store_NUMBER = S.Otb_DEST_store_NBR,
INNER JOIN SHP_LEG Q ON Q.SHPMT_ID = S.SHP_ID
WHERE
W.ACCOUNT_TYPE = 'I'
AND S.Schd_t <= Sysdate
AND Q.Stat_CD IN ('S','P')
ORDER BY Schd_Date);
disconnect from odbc;
QUIT;
However, after i run this i get an error saying "PROC SQL requires any created table to have at least 1 column". Any help to diagnose this issue would be appreciated.

Move the SAS syntax to the SAS side of the query. You also had an extra comma in the middle of the FROM clause. Note if you get in the habit of putting the commas (or any other continuation characters) at the beginning of the line instead of the end they will be easier for the programmers to scan and be sure they are done correctly.
create table School.TRANS_INFO as
SELECT Distinct
Schd_t AS Schd_Date format MMDDYY10.
, otb As Ship_Loc
, store_NUMBER AS store
, SHP_ID AS SHIP_ID
, store_CITY_STATE
, Stat_CD AS Status
, (PROD_CD || plt_CD) AS SKU
, ACCOUNT_TYPE as Location
from connection to odbc
(SELECT Distinct
S.Schd_t
, S.otb
, W.store_NUMBER
, S.SHP_ID
, W.store_CITY_STATE
, Q.Stat_CD
, S.PROD_CD
, S.plt_CD
, W.ACCOUNT_TYPE
FROM SHPMT_DTL S
INNER JOIN store W ON W.store_NUMBER = S.Otb_DEST_store_NBR
INNER JOIN SHP_LEG Q ON Q.SHPMT_ID = S.SHP_ID
WHERE W.ACCOUNT_TYPE = 'I'
AND S.Schd_t <= Sysdate
AND Q.Stat_CD IN ('S','P')
ORDER BY S.Schd_t
);

Related

SQL CASE mixes up my grouping

The problem situates itself at the 4th line of the SELECT statement: CASE WHEN ct.TransactionReason=622 THEN ABS(ct.netquantity) ELSE c.RealNetWeight END AS NetWeight
When I add this line to the statement, my grouping will change. Instead of returning one line it now gives me back the amount of lines of different c.realnetweight.
Problem is that I only want to return one line. Sort of like a coalesce that when there is a ct.transactionreason = 622, it should give me ABS(ct.netquantity), otherwise the c.realnetweight. Code can be found beneath, suggestions would be very helpful. Thanks.
SELECT CASE WHEN P.Wrapped = 1 THEN T.[Level]+1 ELSE T.[Level] END AS [Level]
, #CoilId AS CoilId
, c.SupplierCoilID
, CASE WHEN ct.TransactionReason=622 THEN ABS(ct.netquantity) ELSE c.RealNetWeight END AS NetWeight
, C.RealGrossWeight
, p1.Description
, p1.product
, s.StackID
, s.ProductID
, s.Weight
, P.Product
, P.Description AS 'ProductDescription'
, COUNT(t.BlankId) AS 'NumberOfBlanks'
, c1.Description as 'Status'
, pv.ProductionWeight
, pv.BlankWeight
, t.BlankStatus
FROM #Trace T
INNER JOIN SKUTraceability SKUT ON SKUT.SKUID = T.SKUID
INNER JOIN Stack s ON SKUT.StackID = s.StackID
INNER JOIN Product p ON s.ProductID = p.ProductID
INNER JOIN Coil c ON c.CoilID=#CoilId
INNER JOIN CoilTransaction ct on ct.CoilID=#CoilId
INNER JOIN Product p1 ON c.ProductID=p1.ProductID
INNER JOIN Code c1 ON t.BlankStatus=c1.codenumber AND c1.codetypeid=17
INNER JOIN #ProductVersion pv ON pv.ProductID=p.ProductId AND s.ProductVersion = pv.ProductVersion
WHERE t.BlankId IS NOT NULL
GROUP BY T.[Level]
, c.SupplierCoilID
, CASE WHEN ct.TransactionReason=622 THEN ABS(ct.netquantity) ELSE c.RealNetWeight END
, c.RealGrossWeight
, p1.Description
, p1.product
, s.StackID
, s.ProductID
, s.Weight
, p.Product
, p.Description
, c1.Description
, pv.ProductionWeight
, pv.BlankWeight
, p.Wrapped
, t.BlankStatus
Hard to answer without understanding your table structures however, it appears that CoilTransaction is some sort of transaction table, i.e. a single product can have many transactions.
In your SELECT query, the line causing you issues, is the only line that references your CoilTransaction table therefore I believe, the reason you're returning multiple rows is because you're grouping on a value that is not unique. Also, are transactions individual items because you seem to have a quantity column on the table.
In short, you can't get the grouping you want by including those columns from your transaction table. You would need to elaborate more on what you're trying to accomplish for us to give a more suitable solution. What does that line mean?
For at least one CoilID in table Coil, you will have more than one value in the field netquantity in the table CoilTransaction. This is what is causing the increase in the number of records returned when you include this field in your CASE statement.
I would recommend finding the netquantity value that you want from CoilTransaction in a CTE, and then bringing this in to your CASE statement. For example:
;WITH transaction_summary AS (
SELECT
ct.CoilID,
ct.TransactionReason,
MAX(ct.netquantity) -- choose your aggregate function here
FROM
CoilTransaction ct
GROUP BY
ct.CoilID,
ct.TransactionReason
)
...

Not sure what is causing sql error 306

I originally had the following query on sql:
SELECT PROJECT_TYPE.PROJECT_TYPE_NAME, PROJECT.PROJECT_NAME, STATUS_TYPE.STATUS_TYPE_NAME,
COUNT(*) AS Tasks
FROM TASK
INNER JOIN PROJECT ON PROJECT.PROJECT_ID = TASK.PROJECT_ID
AND PROJECT.POURCENTAGE < 100 /* the following ANDs filters out inactive projects */
AND PROJECT.PROJECT_TYPE < 6
AND PROJECT.PROJECT_STATUS_ID < 3
INNER JOIN PROJECT_TYPE ON PROJECT.PROJECT_TYPE = PROJECT_TYPE.PROJECT_TYPE_ID
INNER JOIN STATUS_TYPE ON TASK.STATUS_TYPE_ID = STATUS_TYPE.STATUS_TYPE_ID
INNER JOIN PRIORITY_TYPE ON TASK.PRIORITY_TYPE_ID = PRIORITY_TYPE.PRIORITY_TYPE_ID
AND NOT PRIORITY_TYPE.PRIORITY_TYPE_NAME = 'Hold'
AND STATUS_TYPE.STATUS_TYPE_NAME IN ('To do','In Progress', 'To Verify') /* only include projects in these 3 statuses */
GROUP BY PROJECT_TYPE.PROJECT_TYPE_NAME, PROJECT.PROJECT_NAME, STATUS_TYPE.STATUS_TYPE_NAME
order by 2, case status_type_name /* orders by status */
when 'To do' then 1
when 'In Progress' then 2
when 'To Verify' then 3
else 4
end
which correctly displayed the count of tasks in a certain status as such. However, I wanted to replace the
project.project_name
table with the shorter description listed in another table called
project.project_desc
, which looks like this. I attempted to implement this by replacing all project.project_name's with project.project_desc, and adding
AND PROJECT.PROJECT_DESC IS NOT NULL
under the first inner join. However, this results in the following error
SQL Error (306): The text, ntext, and image data types cannot be
compared or sorted, except when using IS NULL or LIKE operator.
I'm not sure what's wrong with this now, all of the null values should be filtered out so i'm confused on why the query doesn't run the same way as it did before, just reading a different table instead. I do not have access to edit the database, so these changes must be implemented through the query.
FWIW, I find this easier to read...
SELECT pt.project_type_name
, p.project_name
, st.status_type_name
, COUNT(*) tasks
FROM task t
JOIN project p
ON p.project_id = t.project_id
JOIN project_type pt
ON pt.project_type_id = p.project_type
JOIN status_type st
ON st.status_type_id = t.status_type_id
JOIN priority_type xt
ON xt.priority_type_id = task.priority_type_id
WHERE p.pourcentage < 100
AND p.project_type < 6
AND p.project_status_id < 3
AND xt.priority_type_name != 'hold'
AND st.status_type_name IN('to do','in progress', 'to verify')
GROUP
BY pt.project_type_name
, p.project_name
, st.status_type_name
ORDER
BY p.project_name
, FIELD(status_type_name,'to do','in progress','to verify')

T-SQL: Ugly SQL

EDIT: Just so folks understand, I'm not worried about the formatting, I'm worried about the usage of the GROUP By and the usage of the aggregate fields when it doesn't make a whole lot of sense.
I've been tasked with making some SQL more readable. While I generally know what to do, this particular query escapes me. The gist of the query involves the writer grouping by a whole bunch of fields, and adding those fields to the query results. For fields that he/she doesn't GROUP BY, they use a MIN aggregate function I guess to "make the error go away"
MIN(ISNULL(dbo.V_CONNECT_ContactPartnerDetail_0010.SAPNr, N'')) AS sapkunr,
My difficulty comes from the fact that I can stuff the GROUP BY into a CTE, and then branch out from there, but I've never gotten the row counts to match up between the query I've created and the original one. Any help on making this SQL more readable and making its intent more clear (no functions to make the error go away) would be greatly appreciated.
SELECT dbo.V_CONNECT_ContactPartnerDetail_0010.ID_FI AS firmencode,
dbo.V_CONNECT_ContactPartnerDetail_0010.ID_KP AS partnercode,
dbo.V_CONNECT_ContactPartnerDetail_0010.Nachname,
Min(Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.Vorname, '')) AS vname,
Min(CASE V_CONNECT_ContactPartnerDetail_0010.Anrede
WHEN 'Frau' THEN 2
ELSE 1
END) AS anrede,
Min(Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.EMail, N'')) AS mail,
Min(Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.SAPNr, N'')) AS sapkunr,
Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.Titel, N'') AS titel
FROM dbo.V_CONNECT_ContactPartnerDetail_0010
INNER JOIN dbo.V_CONNECT_ContactPartnerPivot
ON dbo.V_CONNECT_ContactPartnerDetail_0010.ID_C005 = dbo.V_CONNECT_ContactPartnerPivot.ID_C005
LEFT OUTER JOIN dbo.V_CONNECT_Firmen_PZ_Download
ON dbo.V_CONNECT_ContactPartnerDetail_0010.ID_VF = dbo.V_CONNECT_Firmen_PZ_Download.ID_VF
WHERE ( dbo.V_CONNECT_ContactPartnerDetail_0010.VKO = '0010' )
GROUP BY dbo.V_CONNECT_ContactPartnerDetail_0010.ID_FI,
dbo.V_CONNECT_ContactPartnerDetail_0010.ID_KP,
dbo.V_CONNECT_ContactPartnerDetail_0010.Nachname,
dbo.V_CONNECT_ContactPartnerDetail_0010.Ort,
dbo.V_CONNECT_ContactPartnerPivot.flg_spl,
dbo.V_CONNECT_ContactPartnerPivot.flg_ha,
dbo.V_CONNECT_ContactPartnerPivot.flg_fu,
dbo.V_CONNECT_ContactPartnerPivot.flg_ma,
dbo.V_CONNECT_ContactPartnerPivot.flg_ph,
Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.Titel, N'')
This is much more "readable" to me
SELECT cpd.ID_FI AS firmencode
, cpd.ID_KP AS partnercode
, cpd.Nachname AS Nachname
, MIN(ISNULL( cpd.Vorname ,'')) AS vname
, MIN(CASE cpd.Anrede WHEN 'Frau' THEN 2 ELSE 1 END) AS anrede
, MIN(ISNULL( cpd.EMail ,N'')) AS mail
, MIN(ISNULL( cpd.SAPNr ,N'')) AS sapkunr
, ISNULL( cpd.Titel ,N'') AS titel
FROM dbo.V_CONNECT_ContactPartnerDetail_0010 cpd
JOIN dbo.V_CONNECT_ContactPartnerPivot cpp
ON cpd.ID_C005 = cpp.ID_C005
LEFT
JOIN dbo.V_CONNECT_Firmen_PZ_Download fpd
ON fpd.ID_VF = cpd.ID_VF
WHERE cpd.VKO = '0010'
GROUP
BY cpd.ID_FI
, cpd.ID_KP
, cpd.Nachname
, cpd.Ort
, cpp.flg_spl
, cpp.flg_ha
, cpp.flg_fu
, cpp.flg_ma
, cpp.flg_ph
, ISNULL(cpd.Titel ,N'')
EDIT
If I was "tasked with making some SQL more readable", I'd start with the changes above.
Beyond that, it's not clear why the GROUP BY clause includes expression that aren't in the SELECT list. It's valid to do that. But what's curious is that uf there are multiple rows from "cpd" that have different values of "Ort", then there's a pontential to get multiple rows returned, with the same values of "ID_FI", "ID_KP", "Nachname".
What really sticks out though is the outer join to "fpd", and apart from the reference to the "ID_VF" column in the join condition, there aren't any references to columns from "fpd" anywhere else in the query. It seems like if that outer join were removed, we'd get the same result.
The first structural change I would propose would be the removal of the join to "fpd".
SELECT cpd.ID_FI AS firmencode
, cpd.ID_KP AS partnercode
, cpd.Nachname AS Nachname
, MIN(ISNULL( cpd.Vorname ,'')) AS vname
, MIN(CASE cpd.Anrede WHEN 'Frau' THEN 2 ELSE 1 END) AS anrede
, MIN(ISNULL( cpd.EMail ,N'')) AS mail
, MIN(ISNULL( cpd.SAPNr ,N'')) AS sapkunr
, ISNULL( cpd.Titel ,N'') AS titel
FROM dbo.V_CONNECT_ContactPartnerDetail_0010 cpd
JOIN dbo.V_CONNECT_ContactPartnerPivot cpp
ON cpp.ID_C005 = cpd.ID_C005
WHERE cpd.VKO = '0010'
GROUP
BY cpd.ID_FI
, cpd.ID_KP
, cpd.Nachname
, cpd.Ort
, ISNULL( cpd.Titel ,N'')
, cpp.flg_spl
, cpp.flg_ha
, cpp.flg_fu
, cpp.flg_ma
, cpp.flg_ph
We can rearrange the expression in the GROUP BY clause, to move "Title" up with the other columns from "cpd". Without an ORDER BY clause, there's no guarantee what order the rows will be returned in.
We can't tell (from the query, and from the information provided) whether the "ID_C005" column is the PRIMARY KEY or a UNIQUE KEY in either "cpd" or "cpp".
And not knowing that, we can't really make other change to the query without potentially changing the result. If "ID_C005" is unique in "cpp", then we could eliminate all of the "cpp" column references from the GROUP BY.
If the purpose of the inner join (to "cpp") is to filter out rows from "cpd" that don't have a matching row in "cpp", we could make some other changes to the query. And that might make it more "readable".

COUNT field incorrect or syntax error

What would be the error when I get following error message
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[07002]: [Microsoft][ODBC Driver 11 for SQL Server]COUNT field incorrect or syntax error'...
This is the query I'm using
$sql = $pdo->prepare("SELECT stockamount, stockname, stockbalance.stockid, SUM(ABS(reservationtransaction.stockquantity)) AS reservedamount FROM stockbalance
JOIN stock ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction ON reservationtransaction.articleid = :artid
WHERE stockbalance.articleid = :artid AND ((changeddate > DATEADD(yy,-1,GETDATE()) AND inventorydate > DATEADD(yy,-1,GETDATE())) OR stockbalance.stockamount <> 0)
GROUP BY stockbalance.stockid");
$sql->bindValue(':artid', $productId);
$sql->execute();
I have searched questions in SO, but no one was similar or helpful.
Thanks in advance.
Edit: This query is working fine when executing it with Microsoft SQL Server Management Studio, but when using PDO, I'm getting the error.
The number of parameters specified in SQLBindParameter was less than
the number of parameters in the SQL statement contained in
*StatementText. SQLBindParameter was called with ParameterValuePtr set to a null pointer, StrLen_or_IndPtr not set to SQL_NULL_DATA or
SQL_DATA_AT_EXEC, and InputOutputType not set to SQL_PARAM_OUTPUT, so
that the number of parameters specified in SQLBindParameter was
greater than the number of parameters in the SQL statement contained
in *StatementText. SQLExecute Function
placeholders must have unique names even if they have the same value
$sql = $pdo->prepare("SELECT stockamount, stockname, stockbalance.stockid, SUM(ABS(reservationtransaction.stockquantity)) AS reservedamount FROM stockbalance
JOIN stock ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction ON reservationtransaction.articleid = :artid
WHERE stockbalance.articleid = :artid2 AND ((changeddate > DATEADD(yy,-1,GETDATE()) AND inventorydate > DATEADD(yy,-1,GETDATE())) OR stockbalance.stockamount <> 0)
GROUP BY stockbalance.stockid");
$sql->bindValue(':artid', $productId);
$sql->bindValue(':artid2', $productId);
$sql->execute();
Another possibility, if you want to avoid supplying data multiple times (replace the datatype of #artid with the correct data type):
$sql = $pdo->prepare("DECLARE #artid int = :artid
SELECT stockamount, stockname, stockbalance.stockid, SUM(ABS(reservationtransaction.stockquantity)) AS reservedamount FROM stockbalance
JOIN stock ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction ON reservationtransaction.articleid = #artid
WHERE stockbalance.articleid = #artid AND ((changeddate > DATEADD(yy,-1,GETDATE()) AND inventorydate > DATEADD(yy,-1,GETDATE())) OR stockbalance.stockamount <> 0)
GROUP BY stockbalance.stockid");
$sql->bindValue(':artid', $productId);
$sql->execute();
This will only work in an RDBMS that supports DECLARE statements.
All the columns that are not in any arithmetic function must go in the GROUP BY clause. see below:
SELECT stockamount,
stockname,
stockbalance.stockid,
Sum(Abs(reservationtransaction.stockquantity)) AS reservedamount
FROM stockbalance
INNER JOIN stock
ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction
ON reservationtransaction.articleid = :artid
WHERE stockbalance.articleid = :artid
AND ( ( changeddate > Dateadd(yy, -1, Getdate())
AND inventorydate > Dateadd(yy, -1, Getdate()) )
OR stockbalance.stockamount <> 0 )
GROUP BY stockamount,
stockname,
stockbalance.stockid
While GROUP BY is often the culprit for a COUNT issue, I ran into the subject error in SSRS and it was due to a mismatch between the SSRS dataset query and the parameters. The resolution was to ensure each WHERE in the query had a corresponding parameter for the dataset. (I had missed one.)
We had this error when a Django filter statement was trying to substitute more parameters in a query than could be handled by the DB binary. Our query looked roughly like this:
select name, age from Employee where emp_id in (%s)
from a Django statement
Employee.objects.filter(emp_id__in=employee_ids)
The list of emp_id was about 2,100 elements. (The character length of the params substituted was about 10,500).
The hack was to filter in parts and recombine the subsets.

SQL Server 2008 Stored Procedure Performance issue

Hi I have a Stored Procedure
ALTER PROCEDURE [dbo].[usp_EP_GetTherapeuticalALternates]
(
#NDCNumber CHAR(11) ,
#patientid INT ,
#pbmid INT
)
AS
BEGIN
TRUNCATE TABLE TempTherapeuticAlt
INSERT INTO TempTherapeuticAlt
SELECT --PR.ProductID AS MedicationID ,
NULL AS MedicationID ,
PR.ePrescribingName AS MedicationName ,
U.Strength AS MedicationStrength ,
FRM.FormName AS MedicationForm ,
PR.DEAClassificationID AS DEASchedule ,
NULL AS NDCNumber
--INTO #myTemp
FROM DatabaseTwo.dbo.Product PR
JOIN ( SELECT MP.MarketedProductID
FROM DatabaseTwo.dbo.Therapeutic_Concept_Tree_Specific_Product TCTSP
JOIN DatabaseTwo.dbo.Marketed_Product MP ON MP.SpecificProductID = TCTSP.SpecificProductID
JOIN ( SELECT TCTSP.TherapeuticConceptTreeID
FROM DatabaseTwo.dbo.Marketed_Product MP
JOIN DatabaseTwo.dbo.Therapeutic_Concept_Tree_Specific_Product TCTSP ON MP.SpecificProductID = TCTSP.SpecificProductID
JOIN ( SELECT
PR.MarketedProductID
FROM
DatabaseTwo.dbo.Package PA
JOIN DatabaseTwo.dbo.Product PR ON PA.ProductID = PR.ProductID
WHERE
PA.NDC11 = #NDCNumber
) 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 DatabaseTwo.dbo.Product AS P
INNER JOIN DatabaseTwo.dbo.Marketed_Product
AS M ON P.MarketedProductID = M.MarketedProductID
INNER JOIN DatabaseTwo.dbo.Specific_Product
AS S ON M.SpecificProductID = S.SpecificProductID
LEFT OUTER JOIN DatabaseTwo.dbo.OrderableName_Combined
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 DatabaseTwo.dbo.Package AS PA
INNER JOIN DatabaseTwo.dbo.Script_Form
AS S ON PA.NCPDPScriptFormCode = S.NCPDPScriptFormCode
INNER JOIN DatabaseTwo.dbo.FormCode AS F ON S.FormName = F.FormName
GROUP BY PA.ProductID ,
S.ScriptFormID ,
F.Code ,
S.FormName
) FRM ON PR.ProductID = FRM.ProductID
WHERE
( PR.OffMarketDate IS NULL )
OR ( PR.OffMarketDate = '' )
OR (PR.OffMarketDate = '1899-12-30 00:00:00.000')
OR ( PR.OffMarketDate <> '1899-12-30 00:00:00.000'
AND DATEDIFF(dd, GETDATE(),PR.OffMarketDate) > 0
)
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 ,
copay.PharmacyType,
dbo.udf_EP_GetBrandGeneric(LL.ProductID) AS BrandGeneric
FROM TempTherapeuticAlt temp
OUTER APPLY ( SELECT TOP 1
ProductID
FROM DatabaseTwo.dbo.Product
WHERE ePrescribingName = temp.MedicationName
) AS LL
OUTER APPLY [dbo].[udf_EP_tbfGetFormularyStatus](#patientid,
LL.ProductID,
#pbmid) AS fs
OUTER APPLY ( SELECT TOP 1
*
FROM udf_EP_CopayDetails(LL.ProductID,
#PBMID,
fs.ReturnFormulary)
) copay
--ORDER BY LL.ProductID
TRUNCATE TABLE TempTherapeuticAlt
END
On my dev server I have data of 63k in each table
so this procedure took about 30 seconds to return result.
On my Production server, it is timing out, or taking >1 minute.
I am wondering my production server tables are full with 1400 millions of records,
can this be a reason.
if so what can be done, I have all required indexes on tables.
any help would be greatly appreciated.
thanks
Execution Plan
http://www.sendspace.com/file/hk8fao
Major Leakage
OUTER APPLY [dbo].[udf_EP_tbfGetFormularyStatus](#patientid,
LL.ProductID,
#pbmid) AS fs
Some strategies that may help:
Remove the first ORDER BY statement, those are killer on complex queries shouldn't be necessary.
Use CTEs to break the query into smaller pieces that can be individually addressed.
Reduce the nesting in the first set of JOINs
Extract the second and third set of joins (the GROUPED ones) and insert those into a temporary indexed table before joining and grouping everything.
You did not include the definition for function1 or function2 -- custom functions are often a place where performance issues can hide.
Without seeing the execution plan, it's difficult to see where the particular problems may be.
You have a query that selects data from 4 or 5 tables , some of them multiple times. It's really hard to say how to improve without deep analysis of what you are trying to achieve and what table structure actually is.
Data size is definitely an issue; I think it's quite obvious that the more data has to be processed, the longer query will take. Some general advices... Run the query directly and check execution plan. It may reveal bottlenecks. Then check if statistics is up to date. Also, review your tables, partitioning may help a lot in some cases. In addition, you can try altering tables and create clustered index not on PK (as it's done by default unless otherwise specified), but on other column[s] so your query will benefit from certain physical order of records. Note : do it only if you are absolutely sure what you are doing.
Finally, try refactoring your query. I have a feeling that there is a better way to get desired results (sorry, without understanding of table structure and expected results I cannot tell exact solution, but multiple joins of the same tables and bunch of derived tables don't look good to me)

Resources