Syntax Error in Case Statement in SQL Server - sql-server

I am getting syntax error in the below code:
I have made it bold where all I am getting an error. I can use the if-else statement but I really wanto use case statement.
Pls help me with the error.
**CASE** #policy_type
WHEN 'car' THEN
(Select policy_id,customer_id,policy_duration,requested_policy_amount,Car_Age
,Car_Amount
,Number_of_Accidents,estimated_car_premium INTO
#PendingRequest FROM [dbo].[Policy] p join [dbo].[Car_Insurance] c on
p.policy_type_id=c.policy_type_id and p.approved_policy_amount is Null
--And employee_id=#employee_id
join
[dbo].[Car_Insurance_Estimate] c_est on car_age >= c_est.min_car_age and car_age <= c_est.max_car_age
and Car_Amount>=c_est.min_car_amount and Car_Amount<=c_est.max_car_amount and Number_of_Accidents>=c_est.min_accidents
and Number_of_Accidents<=c_est.max_accidents)
**WHEN** 'life' THEN
(Select policy_id,customer_id,policy_duration,requested_policy_amount,Age
,l.Illness
,l.Income
,premium_insurance_percentage,amount_insurance_percentage
INTO
#PendingRequest from [dbo].[Policy] p join [dbo].[life_Insurance] l on
p.policy_type_id=l.policy_type_id and p.approved_policy_amount is Null
And employee_id=#employee_id
join
[dbo].[life_Insurance_Estimate] l_est on age >= l_est.min_age and age <= l_est.max_age
and income>=l_est.min_income and income<=l_est.max_income and l.illness=l_est.illness)
when 'home' then
(Select policy_id,customer_id,policy_duration,requested_policy_amount,home_Age
,home_Amount
,h.Area,home_premium_percentage INTO
#PendingRequest
from [dbo].[Policy] p join [dbo].[home_Insurance] h on
p.policy_type_id=h.policy_type_id and p.approved_policy_amount is Null
And employee_id=#employee_id
join
[dbo].[home_Insurance_Estimate] h_est on home_age >= h_est.min_home_age and home_age <= h_est.max_home_age
and home_Amount>=h_est.min_home_amount and home_Amount<=h_est.max_home_amount and h.Area=h_est.area)
**END**

Using IF...ELSE would be a lot easier in this case. However, if you insist on using CASE, then this might be one option:
DECLARE #SQL varchar(max);
SELECT #SQL=
CASE #policy_type
WHEN 'car' THEN
'Select policy_id,customer_id,policy_duration,requested_policy_amount,Car_Age
,Car_Amount
,Number_of_Accidents,estimated_car_premium INTO
#PendingRequest FROM [dbo].[Policy] p join [dbo].[Car_Insurance] c on
p.policy_type_id=c.policy_type_id and p.approved_policy_amount is Null
--And employee_id=#employee_id
join
[dbo].[Car_Insurance_Estimate] c_est on car_age >= c_est.min_car_age and car_age <= c_est.max_car_age
and Car_Amount>=c_est.min_car_amount and Car_Amount<=c_est.max_car_amount and Number_of_Accidents>=c_est.min_accidents
and Number_of_Accidents<=c_est.max_accidents'
WHEN 'life' THEN
'Select policy_id,customer_id,policy_duration,requested_policy_amount,Age
,l.Illness
,l.Income
,premium_insurance_percentage,amount_insurance_percentage
INTO
#PendingRequest from [dbo].[Policy] p join [dbo].[life_Insurance] l on
p.policy_type_id=l.policy_type_id and p.approved_policy_amount is Null
And employee_id=#employee_id
join
[dbo].[life_Insurance_Estimate] l_est on age >= l_est.min_age and age <= l_est.max_age
and income>=l_est.min_income and income<=l_est.max_income and l.illness=l_est.illness'
WHEN 'home' THEN
'Select policy_id,customer_id,policy_duration,requested_policy_amount,home_Age
,home_Amount
,h.Area,home_premium_percentage INTO
#PendingRequest
from [dbo].[Policy] p join [dbo].[home_Insurance] h on
p.policy_type_id=h.policy_type_id and p.approved_policy_amount is Null
And employee_id=#employee_id
join
[dbo].[home_Insurance_Estimate] h_est on home_age >= h_est.min_home_age and home_age <= h_est.max_home_age
and home_Amount>=h_est.min_home_amount and home_Amount<=h_est.max_home_amount and h.Area=h_est.area'
END
EXEC(#SQL);
Raj

I can use the if-else statement but I really wanto use case statement.
Whenever I see this, I think twice about whether it's a real question being asked. Why?
If you must combine it as one statement, you can put the conditions into the SELECT statements and join them using UNION ALL, only one of which would actually produce results.
--declare #policy_type varchar(10), #employee_id int
Select policy_id,customer_id,policy_duration,requested_policy_amount,Car_Age
,Car_Amount
,Number_of_Accidents,estimated_car_premium
INTO #PendingRequest
FROM [dbo].[Policy] p join [dbo].[Car_Insurance] c on
p.policy_type_id=c.policy_type_id and p.approved_policy_amount is Null
--And employee_id=#employee_id
join
[dbo].[Car_Insurance_Estimate] c_est on car_age >= c_est.min_car_age and car_age <= c_est.max_car_age
and Car_Amount>=c_est.min_car_amount and Car_Amount<=c_est.max_car_amount and Number_of_Accidents>=c_est.min_accidents
and Number_of_Accidents<=c_est.max_accidents
AND #policy_type = 'car'
UNION ALL
Select policy_id,customer_id,policy_duration,requested_policy_amount,Age
,l.Illness
,l.Income
,premium_insurance_percentage,amount_insurance_percentage
from [dbo].[Policy] p join [dbo].[life_Insurance] l on
p.policy_type_id=l.policy_type_id and p.approved_policy_amount is Null
And employee_id=#employee_id
join
[dbo].[life_Insurance_Estimate] l_est on age >= l_est.min_age and age <= l_est.max_age
and income>=l_est.min_income and income<=l_est.max_income and l.illness=l_est.illness
AND #policy_type = 'life'
UNION ALL
Select policy_id,customer_id,policy_duration,requested_policy_amount,home_Age
,home_Amount
,h.Area,home_premium_percentage
from [dbo].[Policy] p join [dbo].[home_Insurance] h on
p.policy_type_id=h.policy_type_id and p.approved_policy_amount is Null
And employee_id=#employee_id
join
[dbo].[home_Insurance_Estimate] h_est on home_age >= h_est.min_home_age and home_age <= h_est.max_home_age
and home_Amount>=h_est.min_home_amount and home_Amount<=h_est.max_home_amount and h.Area=h_est.area
AND #policy_type = 'home';
If it's some silly assignment requirement, then you can make a benign change to the last row, say
AND CASE #policy_type WHEN 'home' then 1 else 0 END = 1;

instead of case , u can use if statement
if #policy_type = 'Car'
BEGIN
Query1
END
ELSE IF (#policy_type = 'life')
BEGIN
Query2
END
and thus ur #table will be accessasble every where

Related

How to get a windowed function working in WHERE clause

I know that there are quite many threads on "Windowed functions can only appear in the select or ORDER BY clases" topic, but I have read them through and just don't seem to get any of those trick to work for me. So here I go.
My Query you can see below the line. I have highlighted the part of the Query which is "causing" me issues or problems. The thing is that I would like to get
"LocalCurrentAmount not between -1.000000 and 1.000000"
in somehow. I have tried the CTE versioon, but somehow didn't work and my declare tables and then the details view started causing problems.
Would really appreciate your help!
Jaanis
declare #exceptions1 table (CustomerCode varchar(7), Exception_comment varchar(15));
insert into #exceptions1 (CustomerCode, Exception_comment)
VALUES
(3514437,'Exception'),(3500977,'Exception'),(3295142,'Exception'), ...
declare #exceptions2 table (CustomerCode2 varchar(7), Exception_comment2 varchar(15));
insert into #exceptions2 (CustomerCode2, Exception_comment2)
VALUES
(3390437,'VIP SE') ,(3390438,'VIP SE') ,(3390481,'VIP SE'), ...
declare #exceptions3 table (CustomerCode3 varchar(7), Exception_comment3 varchar(15));
insert into #exceptions1 (CustomerCode, Exception_comment)
VALUES
(1530350, 'DK Exception'), (1533834, 'DK Exception'), (1530002, 'DK Exception'), ...
with Details as
(
select ard.AccountsReceivableHeaderID, sum(ard.TransactionAmountOC) as DetailAmountOC , Max(DetailSequenceCode) as DetailSequenceCode, Max( ard.BatchDate) as BatchDate
from dmbase.fAccountsReceivableDetail ard
join dmbase.fAccountsReceivable arh on ard.AccountsReceivableHeaderID = arh.AccountsReceivableID
where ard.BatchDate <= getdate()
group by AccountsReceivableHeaderID
)
SELECT
comp.CompanyCode
,convert(varchar(10),ar.InvoiceDate, 103) as Invoice_date -- dd/MM/yyyy format
,case
when ar.IsCreditMemo = 'Y' then 'Memo (Credit/Debit)'
when ar.InvoiceCode = '0' then 'Payment'
else 'Invoice'
end as Description
,isnull(cm.SummaryInvoiceCode, ar.InvoiceSummaryCode) InvoiceSummaryCode
,case
when len(ar.InvoiceSequenceCode) = '1' then CONCAT(ar.InvoiceCode,'-000',ar.InvoiceSequenceCode)
when len(ar.InvoiceSequenceCode) = '2' then CONCAT(ar.InvoiceCode,'-00',ar.InvoiceSequenceCode)
when len(ar.InvoiceSequenceCode) = '3' then CONCAT(ar.InvoiceCode,'-0',ar.InvoiceSequenceCode)
else CONCAT(ar.InvoiceCode,'-',ar.InvoiceSequenceCode)
end as Invoice#
,**(ar.OriginalInvoiceAmountOC
+
case
when row_number() over (partition by AccountsReceivableID order by ar.InvoiceCode) = 1 then isnull(vat.vatAdjustment, 0)
else 0
end
+
coalesce(det.DetailAmountOC, 0)) * coalesce(cer.CurrencyExchangeRate, ar.CurrencyExchangeRate) AS LocalCurrentAmount**
,(ar.OriginalInvoiceAmountOC
+
case
when row_number() over (partition by AccountsReceivableID order by ar.InvoiceCode) = 1 then isnull(vat.vatAdjustment, 0)
else 0
end
+ coalesce(det.DetailAmountOC, 0)) AS CurrentAmount
,ar.OriginalInvoiceAmountOC
+
case
when row_number() over (partition by AccountsReceivableID order by ar.InvoiceCode) = 1 then isnull(vat.vatAdjustment, 0)
else 0
end as OriginalInvoiceAmountOC
,ar.InvoiceCurrencyCode
,cust.CustomerCode
,upper(cust.CustomerName) as CustomerName
from
dmbase.fAccountsReceivable ar
INNER JOIN dmbase.dlocation loc
ON loc.LocationID = ar.LocationID
INNER JOIN dmbase.dCustomer cust
ON cust.CustomerID = ar.CustomerID
LEFT JOIN dmbase.VatAdjustment vat
on ar.InvoiceCode = vat.contractNumber
and ar.InvoiceSequenceCode = vat.invoiceSequence
and cust.CustomerCode = vat.CustomerNumber
and loc.CompanyCode = vat.companyCode
inner join dmbase.dCompany comp
on (ar.CompanyID = comp.CompanyID)
left join dmbase.dAccountsReceivableInvoiceStatus aris
on (aris.ARInvoiceStatusAMID=ar.ARInvoiceStatusAMID)
left hash join Details det
on (ar.AccountsReceivableID = det.AccountsReceivableHeaderID)
left join dmbase.dCurrencyExchangeRate cer
on (comp.CompanyCode = cer.CompanyCode
and ar.InvoiceCurrencyCode = cer.CurrencyCode
and case ar.InvoiceDate when '1900-01-01' then getdate() else ar.InvoiceDate end between cer.ValidFrom and cer.ValidTo)
left join dmbase.fContractClosedHeader ccd
on ccd.ContractNumber = ar.InvoiceCode
and ccd.ContractSeqNumber = ar.InvoiceSequenceCode
and ccd.CompanyID = ar.CompanyID
and ccd.ContractNumber!='0'
and ccd.CreditMemoContractNumber != '0'
left join dmbase.fAccountsReceivableHeader cm
on ccd.CreditMemoContractNumber = cm.ContractNumber
and ccd.CreditMemoSequenceCode = cm.ContractSeqNumber
and cm.CompanyID = ccd.CompanyID
where
(aris.ARInvoiceStatusCode = 'OP' or (ar.LastPaymentDate >= getdate())
or (ar.TotalAdjustmentsAmountOC <> 0 and ar.CurrentAmountLC = 0
and (ar.OriginalInvoiceAmountOC + isnull(vat.vatAdjustment, 0) ) + coalesce(det.DetailAmountOC, 0) <> 0)
)
and ar.OriginalInvoiceAmountOC <= 0
and ar.IsCreditMemo = 'Y' -- ainult Memo (Credit/Debit)
and cust.InternalCustomerType = 'External'
and cust.CustomerName not in ('RR AJM', 'RAMIRENT', 'Ramirent')
and cust.CustomerName not like '%[7][0-9][0-9][0-9]%'
and ar.InvoiceDate <= EOMONTH(getdate(),-3
and cust.CustomerCode NOT IN
(select CustomerCode from #exceptions1
union
select CustomerCode2 from #exceptions2
union
select CustomerCode3 from #exceptions3)
order by Invoice_date
When using a Window function, like you said in your post, you can't use it in the WHERE clause. The common solution, therefore, is to use a CTE and reference it in the WHERE outside of it. I've used your CTE, however, without any kind of sample data this is a total guess. I've also left a lot of comments for you, and changed some other parts of the SQL, as some of the clauses you have will effect your query's performance.
WITH
Details AS
(SELECT ard.AccountsReceivableHeaderID,
SUM(ard.TransactionAmountOC) AS DetailAmountOC,
MAX(DetailSequenceCode) AS DetailSequenceCode,
MAX(ard.BatchDate) AS BatchDate
FROM dmbase.fAccountsReceivableDetail ard
JOIN dmbase.fAccountsReceivable arh ON ard.AccountsReceivableHeaderID = arh.AccountsReceivableID
WHERE ard.BatchDate <= GETDATE()
GROUP BY AccountsReceivableHeaderID),
Summary AS(
SELECT comp.CompanyCode,
CONVERT(varchar(10), ar.InvoiceDate, 103) AS Invoice_date, -- dd/MM/yyyy format
CASE
WHEN ar.IsCreditMemo = 'Y' THEN 'Memo (Credit/Debit)'
WHEN ar.InvoiceCode = '0' THEN 'Payment'
ELSE 'Invoice'
END AS Description,
ISNULL(cm.SummaryInvoiceCode, ar.InvoiceSummaryCode) AS InvoiceSummaryCode,
CASE
WHEN LEN(ar.InvoiceSequenceCode) = '1' THEN CONCAT(ar.InvoiceCode, '-000', ar.InvoiceSequenceCode)
WHEN LEN(ar.InvoiceSequenceCode) = '2' THEN CONCAT(ar.InvoiceCode, '-00', ar.InvoiceSequenceCode)
WHEN LEN(ar.InvoiceSequenceCode) = '3' THEN CONCAT(ar.InvoiceCode, '-0', ar.InvoiceSequenceCode)
ELSE CONCAT(ar.InvoiceCode, '-', ar.InvoiceSequenceCode)
END AS Invoice#,
(ar.OriginalInvoiceAmountOC + CASE
WHEN ROW_NUMBER() OVER (PARTITION BY AccountsReceivableID ORDER BY ar.InvoiceCode) = 1 THEN ISNULL(vat.vatAdjustment, 0)
ELSE 0
END + COALESCE(det.DetailAmountOC, 0)) * COALESCE(cer.CurrencyExchangeRate, ar.CurrencyExchangeRate) AS LocalCurrentAmount,
(ar.OriginalInvoiceAmountOC + CASE
WHEN ROW_NUMBER() OVER (PARTITION BY AccountsReceivableID ORDER BY ar.InvoiceCode) = 1 THEN ISNULL(vat.vatAdjustment, 0)
ELSE 0
END + COALESCE(det.DetailAmountOC, 0)) AS CurrentAmount,
ar.OriginalInvoiceAmountOC + CASE
WHEN ROW_NUMBER() OVER (PARTITION BY AccountsReceivableID ORDER BY ar.InvoiceCode) = 1 THEN ISNULL(vat.vatAdjustment, 0)
ELSE 0
END AS OriginalInvoiceAmountOC,
ar.InvoiceCurrencyCode,
cust.CustomerCode,
UPPER(cust.CustomerName) AS CustomerName
FROM dmbase.fAccountsReceivable ar
INNER JOIN dmbase.dlocation loc ON loc.LocationID = ar.LocationID
INNER JOIN dmbase.dCustomer cust ON cust.CustomerID = ar.CustomerID
LEFT JOIN dmbase.VatAdjustment vat ON ar.InvoiceCode = vat.contractNumber
AND ar.InvoiceSequenceCode = vat.invoiceSequence
AND cust.CustomerCode = vat.CustomerNumber
AND loc.CompanyCode = vat.companyCode
INNER JOIN dmbase.dCompany comp ON (ar.CompanyID = comp.CompanyID)
LEFT JOIN dmbase.dAccountsReceivableInvoiceStatus aris ON (aris.ARInvoiceStatusAMID = ar.ARInvoiceStatusAMID)
LEFT HASH JOIN Details det ON (ar.AccountsReceivableID = det.AccountsReceivableHeaderID)
LEFT JOIN dmbase.dCurrencyExchangeRate cer ON (comp.CompanyCode = cer.CompanyCode
AND ar.InvoiceCurrencyCode = cer.CurrencyCode
AND CASE ar.InvoiceDate WHEN '1900-01-01' THEN GETDATE()ELSE ar.InvoiceDate END BETWEEN cer.ValidFrom AND cer.ValidTo)
LEFT JOIN dmbase.fContractClosedHeader ccd ON ccd.ContractNumber = ar.InvoiceCode
AND ccd.ContractSeqNumber = ar.InvoiceSequenceCode
AND ccd.CompanyID = ar.CompanyID
AND ccd.ContractNumber != '0'
AND ccd.CreditMemoContractNumber != '0'
LEFT JOIN dmbase.fAccountsReceivableHeader cm ON ccd.CreditMemoContractNumber = cm.ContractNumber
AND ccd.CreditMemoSequenceCode = cm.ContractSeqNumber
AND cm.CompanyID = ccd.CompanyID
WHERE (aris.ARInvoiceStatusCode = 'OP'
OR (ar.LastPaymentDate >= GETDATE())
OR (ar.TotalAdjustmentsAmountOC <> 0
AND ar.CurrentAmountLC = 0
AND (ar.OriginalInvoiceAmountOC + ISNULL(vat.vatAdjustment, 0)) + COALESCE(det.DetailAmountOC, 0) <> 0)) --Why ISNULL for one, COALESCE for the other? Both will make the query non-SARGable
AND ar.OriginalInvoiceAmountOC <= 0
AND ar.IsCreditMemo = 'Y' -- ainult Memo (Credit/Debit)
AND cust.InternalCustomerType = 'External'
AND cust.CustomerName NOT IN ('RR AJM', 'RAMIRENT', 'Ramirent')
AND cust.CustomerName NOT LIKE '%[7][0-9][0-9][0-9]%' --A leading wildcard is going to perform slow
AND ar.InvoiceDate <= EOMONTH(DATEADD(DAY, -3, GETDATE())) --I have changed this from EOMONTH(GETDATE(), -3 (which made no sense)
AND NOT EXISTS (SELECT 1
FROM #exceptions1 E
WHERE E.CustomerCode = cust.CustomerCode) --Changed to EXISTS binned UNION you should use UNION ALL if you're doing something like this, it'll be quicker)
AND NOT EXISTS (SELECT 1
FROM #exceptions2 E
WHERE E.CustomerCode = cust.CustomerCode) --Changed to EXISTS binned UNION (you should use UNION ALL if you're doing something like this, it'll be quicker)
AND NOT EXISTS (SELECT 1
FROM #exceptions3 E
WHERE E.CustomerCode = cust.CustomerCode)) --Changed to EXISTS binned UNION you should use UNION ALL if you're doing something like this, it'll be quicker)
SELECT *
FROM Summary
WHERE LocalCurrentAmount NOT BETWEEN -1 AND 1
ORDER BY Invoice_date;
It's worth noting that the above sql is completely untested. I do not have access to your server, or data, so I'm purely relying on "my eye" to note any errors.

Combining multiple SQL's into a single SQL

Hi have the following queries
(SELECT COUNT(DISTINCT KUNDNR) CHECKED_CUSTOMER from CLNT0001.TCM_CHECK_SUMMARY
where '20170322000000000' <= HISTVON and HISTVON < '20170323000000000' and INSTITUTSNR='0001')
and
SELECT clientNumber
,creationDate
,customerNumber
,checkedCustomer
,CLNT0001.TCM_CHECK_SUMMARY.COUNTRY_CODE countryCode
,CLNT0001.TCM_CHECK_SUMMARY.PST_KURZTEXT personStatus
,CLNT0001.TCM_CASE_COUNTRY_GROUP.COUNTRY_CODE homeCountryCode
,CLNT0001.TCM_CASE_COUNTRY_GROUP.PST_LFD_NR personStatusId
,CLNT0001.TCM_CASE_COUNTRY_GROUP.REGULATION regulation
,caseStatus
,COC_SCORE_COUNT cocCaseCount
FROM (
SELECT GEPRUEFT_JN checkedCustomer
,INSTITUTSNR clientNumber
,KUNDNR customerNumber
,CASE_STATUS caseStatus
,MAX(CREATION_DATE) creationDate
FROM CLNT0001.TAXACTCASE
WHERE GEPRUEFT_JN = 'J' AND CREATION_DATE>='20170322000000000' AND
CREATION_DATE<='20170323000000000'
GROUP BY KUNDNR
,INSTITUTSNR
,GEPRUEFT_JN
,CASE_STATUS
) T1
INNER JOIN CLNT0001.TCM_CHECK_SUMMARY ON T1.customerNumber = CLNT0001.TCM_CHECK_SUMMARY.KUNDNR
INNER JOIN CLNT0001.TCM_CASE_COUNTRY_GROUP ON T1.customerNumber = CLNT0001.TCM_CASE_COUNTRY_GROUP.KUNDNR
WHERE T1.creationDate <= CLNT0001.TCM_CHECK_SUMMARY.HISTBIS
AND T1.creationDate >= CLNT0001.TCM_CHECK_SUMMARY.HISTVON
I need the CHECKED_CUSTOMER column as a part of the second query's result set, i am not able to figure out a way to do this, is this possible ?
SELECT clientNumber,creationDate,customerNumber,checkedCustomer
,CLNT0001.TCM_CHECK_SUMMARY.COUNTRY_CODE countryCode
,CLNT0001.TCM_CHECK_SUMMARY.PST_KURZTEXT personStatus
,CLNT0001.TCM_CASE_COUNTRY_GROUP.COUNTRY_CODE homeCountryCode
,CLNT0001.TCM_CASE_COUNTRY_GROUP.PST_LFD_NR personStatusId
,CLNT0001.TCM_CASE_COUNTRY_GROUP.REGULATION regulation
,caseStatus,COC_SCORE_COUNT cocCaseCount ,CHECKED_CUSTOMER
FROM (
SELECT GEPRUEFT_JN checkedCustomer,INSTITUTSNR clientNumber ,KUNDNR customerNumber ,CASE_STATUS caseStatus,MAX(CREATION_DATE) creationDate,COUNT(DISTINCT b.KUNDNR) CHECKED_CUSTOMER
FROM CLNT0001.TAXACTCASE
LEFT JOIN CLNT0001.TCM_CHECK_SUMMARY b ON CLNT0001.TAXACTCASE.KUNDNR=b.KUNDNR
WHERE GEPRUEFT_JN = 'J' AND CREATION_DATE>='20170322000000000' AND
CREATION_DATE<='20170323000000000'
GROUP BY KUNDNR,INSTITUTSNR ,GEPRUEFT_JN,CASE_STATUS
) T1 INNER JOIN CLNT0001.TCM_CHECK_SUMMARY ON T1.customerNumber = CLNT0001.TCM_CHECK_SUMMARY.KUNDNR
INNER JOIN CLNT0001.TCM_CASE_COUNTRY_GROUP ON T1.customerNumber = CLNT0001.TCM_CASE_COUNTRY_GROUP.KUNDNR
WHERE T1.creationDate <= CLNT0001.TCM_CHECK_SUMMARY.HISTBIS
AND T1.creationDate >= CLNT0001.TCM_CHECK_SUMMARY.HISTVON

Data result should appear on one column

I am a self learner in SQL; I have created this code:
SELECT T0.[CardName], T0.[DocDate], T0.[DocDueDate], T2.[U_ExpDelDate], T0.[DocStatus], T1.[SlpName],
CASE
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) <= 0 THEN 'Delivered'
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) >= 0 THEN 'Please Check'
ELSE NULL END AS 'Status',
DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) AS 'Age'
FROM OPOR T0 INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode] INNER JOIN POR1 T2 ON T0.[DocEntry] = T2.[DocEntry]
WHERE T0.[DocStatus] ='O' and T2.[U_ExpDelDate] is not null
I am getting the right result, but now I wanted Join the result Delivered and Please Check in Age column.
Do you have any idea?
Concatenating strings in sql server is done by either using the + operator or the CONCAT method.
Try this:
SELECT T0.[CardName], T0.[DocDate], T0.[DocDueDate], T2.[U_ExpDelDate], T0.[DocStatus], T1.[SlpName],
CASE
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) <= 0 THEN 'Delivered '
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) > 0 THEN 'Please Check ' + CAST(DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) as varchar)
END AS 'Age'
FROM OPOR T0 INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode] INNER JOIN POR1 T2 ON T0.[DocEntry] = T2.[DocEntry]
WHERE T0.[DocStatus] ='O' and T2.[U_ExpDelDate] is not null
I've removed the else part since it's never going there, the datediff function will either return a value that is less than or equal to 0 or more than 0.

SQL Server query that contains a derived table

I have created a select query that contains one regular table and two derived tables (subqueries). The derived tables are both joined with the regular table with left joins. The regular table contains over 7000 rows, but the query output is around 3000 rows. It has to be equal to the number of records in the regular table. What is my mistake?
SELECT T0.[ItemCode],
T0.[ItemName],
CASE T0.[PrcrmntMtd] WHEN 'B' THEN 'Inkoop' ELSE 'Productie' END AS Verwervingsmethode,
T0.[OnHand] AS Voorraad_excl_grondstof_reeds_verwerkt,
T1.[Reeds_geproduceerd] AS Grondstof_reeds_verwerkt,
CASE WHEN T1.[Reeds_geproduceerd] IS NULL
THEN T0.[OnHand]
ELSE T0.[OnHand]-T1.[Reeds_geproduceerd]
END AS Voorraad_incl_grondstof_reeds_verwerkt,
T2.[Nog_te_produceren] AS Geplande_productie_halffabrikaat_eindproduct,
T1.[Nog_te_produceren] AS Gereserveerd_voor_productie_grondstof_halffabrikaat,
CASE WHEN T1.[Reeds_geproduceerd] IS NULL
THEN (T0.[OnHand]/T2.[Nog_te_produceren])*30
ELSE ((T0.[OnHand]-T1.[Reeds_geproduceerd])/T2.[Nog_te_produceren])*30
END AS Dagen_voorraad_halffabrikaat_eindproduct,
CASE WHEN T1.[Reeds_geproduceerd] IS NULL
THEN (T0.[OnHand]/T1.[Nog_te_produceren])*30
ELSE ((T0.[OnHand]-T1.[Reeds_geproduceerd])/T1.[Nog_te_produceren])*30
END AS Dagen_voorraad_grondstof_halffabrikaat
FROM OITM T0
LEFT JOIN (
SELECT T1.[ItemCode],
SUM(T0.[PlannedQty]*T1.[BaseQty]) AS Geplande_productie,
CASE WHEN SUM(T0.CmpltQty) IS NULL THEN SUM(T0.[PlannedQty]*T1.[BaseQty]) ELSE SUM(T0. [CmpltQty]*T1.[BaseQty]) END AS Reeds_geproduceerd,
CASE WHEN SUM(T0.CmpltQty) IS NULL THEN SUM(T0.[PlannedQty]*T1.[BaseQty]) ELSE SUM(T0.[PlannedQty]*T1.[BaseQty])-SUM(T0.[CmpltQty]*T1.[BaseQty]) END AS Nog_te_produceren
FROM OWOR T0
INNER JOIN WOR1 T1 ON T0.DocEntry = T1.DocEntry
WHERE T0.DueDate <= getdate()+30
AND (T0.[Status] LIKE 'p'
OR T0.[Status] LIKE 'r')
GROUP BY T1.[ItemCode]
) AS T1
ON T0.ItemCode = T1.ItemCode
LEFT JOIN (
SELECT T0.[ItemCode],
SUM(T0.[PlannedQty]) AS Geplande_productie,
SUM(T0.[CmpltQty]) AS Reeds_geproduceerd,
SUM(T0.[PlannedQty])-SUM(T0.[CmpltQty]) AS Nog_te_produceren
FROM OWOR T0
INNER JOIN WOR1 T1 ON T0.DocEntry = T1.DocEntry
WHERE T0.DueDate <= getdate()+30
AND (T0.[Status] LIKE 'p'
OR T0.[Status] LIKE 'r')
GROUP BY T0.[ItemCode]
) AS T2
ON T0.ItemCode = T2.ItemCode
I mentioned all the where clauses. If I red the linked page correct, that cant be the problem.
I also changed the table names and column names of the derived tables. Now all table names and column names are unique.
But still the same problem. When i delete the last two case statements in select, i do get all the output lines, but i dont see any problems in these case statements.
SELECT T0.[ItemCode],
T0.[ItemName],
CASE T0.[PrcrmntMtd] WHEN 'B' THEN 'Inkoop' ELSE 'Productie' END AS Verwervingsmethode,
T0.[OnHand] AS Voorraad_excl_grondstof_reeds_verwerkt,
T3.[Reeds_geproduceerd_grond] AS Grondstof_reeds_verwerkt,
CASE WHEN T3.[Reeds_geproduceerd_grond] IS NULL
THEN T0.[OnHand]
ELSE T0.[OnHand]-T3.[Reeds_geproduceerd_grond]
END AS Voorraad_incl_grondstof_reeds_verwerkt,
T6.[Nog_te_produceren_eind] AS Geplande_productie_halffabrikaat_eindproduct,
T3.[Nog_te_produceren_grond] AS Gereserveerd_voor_productie_grondstof_halffabrikaat,
CASE WHEN T3.[Reeds_geproduceerd_grond] IS NULL
THEN 30*(T0.[OnHand]/T6.[Nog_te_produceren_eind])
ELSE 30*((T0.[OnHand]-T3.[Reeds_geproduceerd_grond])/T6.[Nog_te_produceren_eind])
END AS Dagen_voorraad_halffabrikaat_eindproduct,
CASE WHEN T3.[Reeds_geproduceerd_grond] IS NULL
THEN 30*(T0.[OnHand]/T3.[Nog_te_produceren_grond])
ELSE 30*((T0.[OnHand]-T3.[Reeds_geproduceerd_grond])/T3.[Nog_te_produceren_grond])
END AS Dagen_voorraad_grondstof_halffabrikaat
FROM OITM T0
LEFT JOIN (
SELECT T2.[ItemCode] AS ItemCode_grond,
SUM(T1.[PlannedQty]*T2.[BaseQty]) AS Geplande_productie_grond,
CASE WHEN SUM(T1.CmpltQty) IS NULL
THEN SUM(T1.[PlannedQty]*T2.[BaseQty])
ELSE SUM(T1.[CmpltQty]*T2.[BaseQty])
END AS Reeds_geproduceerd_grond,
CASE WHEN SUM(T1.CmpltQty) IS NULL
THEN SUM(T1.[PlannedQty]*T2.[BaseQty])
ELSE SUM(T1.[PlannedQty]*T2.[BaseQty])-SUM(T1.[CmpltQty]*T2.[BaseQty])
END AS Nog_te_produceren_grond
FROM OWOR T1
INNER JOIN WOR1 T2 ON T1.DocEntry = T2.DocEntry
WHERE T1.DueDate <= getdate()+30
AND (T1.[Status] LIKE 'p'
OR T1.[Status] LIKE 'r')
GROUP BY T2.[ItemCode]
) AS T3
ON T0.ItemCode = T3.ItemCode_grond
LEFT JOIN (
SELECT T4.[ItemCode] AS ItemCode_eind,
SUM(T4.[PlannedQty]) AS Geplande_productie_eind,
SUM(T4.[CmpltQty]) AS Reeds_geproduceerd_eind,
SUM(T4.[PlannedQty])-SUM(T4.[CmpltQty]) AS Nog_te_produceren_eind
FROM OWOR T4
INNER JOIN WOR1 T5 ON T4.DocEntry = T5.DocEntry
WHERE T4.DueDate <= getdate()+30
AND (T4.[Status] LIKE 'p'
OR T4.[Status] LIKE 'r')
GROUP BY T4.[ItemCode]
) AS T6
ON T0.ItemCode = T6.ItemCode_eind

Joining on varchar(50) foreign key slows query

I have this query which is pretty long, but adding a where clause to it, or joining on a string makes it take an extra 2 seconds to run. I can't figure out why.
Here's the query in full:
ALTER PROCEDURE [dbo].[RespondersByPracticeID]
#practiceID int = null,
#activeOnly bit = 1
AS
BEGIN
SET NOCOUNT ON;
select
isnull(sum(isResponder),0) as [Responders]
,isnull(count(*) - sum(isResponder),0) as [NonResponders]
,isnull((select
count(p.patientID)
from patient p
inner join practice on practice.practiceid = p.practiceid
inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd'
where
p.practiceID = isnull(#practiceID, p.practiceID)
and p.active = case #activeOnly when 1 then 1 else p.active end
) - (isnull(sum(isResponder),0) + isnull(count(*) - sum(isResponder),0)),0)
as [Undetermined]
from (
select
v.patientID
,firstVisit.hbLevel as startHb
,maxHbVisit.hblevel as maxHb
, case when (maxHbVisit.hblevel - firstVisit.hbLevel >= 1) then 1 else 0 end as isResponder
,count(v.patientID) as patientCount
from patient p
inner join visit v on v.patientid = v.patientid
inner join practice on practice.practiceid = p.practiceid
inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd'
inner join (
SELECT
p.PatientID
,v.VisitID
,v.hblevel
,v.VisitDate
FROM Patient p
INNER JOIN Visit v ON p.PatientID = v.PatientID
WHERE
v.VisitDate = (
SELECT MIN(VisitDate)
FROM Visit
WHERE PatientId = p.PatientId
)
) firstVisit on firstVisit.patientID = v.patientID
inner join (
select
p.patientID
,max(v.hbLevel) as hblevel
from Patient p
INNER JOIN Visit v ON p.PatientID = v.PatientID
group by
p.patientID
) MaxHbVisit on maxHbVisit.patientid = v.patientId
where
p.practiceID = isnull(#practiceID, p.practiceID)
and p.active = case #activeOnly when 1 then 1 else p.active end
group by
v.patientID
,firstVisit.hbLevel
,maxHbVisit.hblevel
having
datediff(
d,
dateadd(
day
,-DatePart(
dw
,min(v.visitDate)
) + 1
,min(v.visitDate)
)
, max(v.visitDate)
) >= (7 * 8) -- Eight weeks.
) responders
END
The line that slows it down is:
inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd'
Also, moving it to the where clause has the same effect:
where p.dosing = 'da_ncd'
Otherwise, the query runs almost instantly. >.<
Ah, sorry I figured it out. Patient.Dosing was set as allow nulls. I guess that made it a different sort of index.
For the record, even though the question is answered.
Usually things like this happen because the execution plan is changed. Compare the plans in query analyzer.
Another gotcha is data types - if p.dosing and l.lookupid differ - nvarchar vs. varchar, for example, can have a huge impact.
Try creating an index on that table, being sure to properly include that VARCHAR field in the list of fields.

Resources