TSQL Updating a record within a select statement - sql-server

When retrieving a data set via a select statement, I want to update existing records based on the vales in columns for each retrieved record. I can't use a function to update a record and I can't use a stored procedure in a select statement. I also fount that I cannot circumvent these restrictions by executing a stored procedure from a function.
Any ideas? Following is my current code with a comment where I feel I need to call something that will update the record. This code will be used in SSRS so one solution might be to execute a stored procedure inside the reports custom code but I cant get that to work either.
select sw.SMACTVSEQ as JDE_ActiveRec
,sw.SMCSSEQ as JDE_SalesSeq
,bu.MCRP04 as JDE_DivID
,sw.SMHBMCUS as JDE_CommID
,cm.CMDL01 as JDE_CommunityName
,rtrim(sw.SMMCU) as JDE_LotID
,sw.SMBYR as JDE_BuyerABNo
,JDE_SSID = case
When ab.ABURRF is null then cast(0 as int)
When ab.ABURRF = '' then cast(0 as int)
else cast(ab.ABURRF as int)
end
,ss.Customer_ID as SS_CustID
,ss.Lot_ID as SS_LotID
,ss.Customer_Status as SS_CustStatus
,[dbo].[udf_ConvertJDEdate](sw.SMCDJ) as JDE_DateClosed
,case when ab.ABURRF >0 then 'Manually Update'
else
case when #Update_Mode ='Yes' then
'Yes/Error'
/* **************
Replace 'Yes/Error' with procedure to update
JDE_F0101_ABURRF and return 'Yes' or 'Error'
************** */
else #Update_Mode
end
end as Update_Mode
from [dbo].[crp_F44H501] sw
left outer join [dbo].[crp_F44H101] cm
on cm.[CMHBMCUS]=sw.smhbmcus and cm.[CMCPHASE]=sw.[SMCPHASE]
left outer join [dbo].[crp_F0006] bu
on bu.mcmcu = sw.smmcu
left outer join [dbo].[stg_F0101] ab
on ab.aban8 = sw.SMBYR
left outer join (
select distinct(lot_id)
,customer_ID
,customer_status
from [dbo].[SS_FactDemographic]
) ss
on ltrim(ss.lot_id) = ltrim(sw.SMMCU)
Where sw.smactvseq='1'
and sw.SMBYR > 0
and ab.ABURRF <> ss.Customer_ID
and ss.Customer_Status = 'Buyer'
and (bu.MCRP04 = #Division_ID or #Division_ID ='All')
and (ltrim(sw.SMHBMCUS) = #Community_ID or #Community_ID ='All')
Order by JDE_DivID,JDE_CommID,JDE_LotID

Put the UPDATE query in the TSQL of the report query before your data query. As long as your query is valid and you have permission, SSRS will run TSQL to UPDATE data, use TEMP tables, etc. The SSRS Query Editor may not like everything that you can do so you might need to make your query in SSMS (which I usually do anyways).
I think your query would look something like:
UPDATE sw
SET Update_Mode = CASE WHEN ab.ABURRF >0 THEN 'Manually Update'
ELSE CASE WHEN #Update_Mode ='Yes' THEN 'Yes/Error' ELSE #Update_Mode END
END
FROM [dbo].[crp_F44H501] sw
INNER JOIN [dbo].[stg_F0101] ab on ab.aban8 = sw.SMBYR
select sw.SMACTVSEQ as JDE_ActiveRec
,sw.SMCSSEQ as JDE_SalesSeq
,bu.MCRP04 as JDE_DivID
,sw.SMHBMCUS as JDE_CommID
,cm.CMDL01 as JDE_CommunityName
,rtrim(sw.SMMCU) as JDE_LotID
,sw.SMBYR as JDE_BuyerABNo
,JDE_SSID = case
When ab.ABURRF is null then cast(0 as int)
When ab.ABURRF = '' then cast(0 as int)
else cast(ab.ABURRF as int)
end
,ss.Customer_ID as SS_CustID
,ss.Lot_ID as SS_LotID
,ss.Customer_Status as SS_CustStatus
,[dbo].[udf_ConvertJDEdate](sw.SMCDJ) as JDE_DateClosed
,sw.Update_Mode
from [dbo].[crp_F44H501] sw
left outer join [dbo].[crp_F44H101] cm
on cm.[CMHBMCUS]=sw.smhbmcus and cm.[CMCPHASE]=sw.[SMCPHASE]
left outer join [dbo].[crp_F0006] bu
on bu.mcmcu = sw.smmcu
left outer join [dbo].[stg_F0101] ab
on ab.aban8 = sw.SMBYR
left outer join (
select distinct(lot_id)
,customer_ID
,customer_status
from [dbo].[SS_FactDemographic]
) ss
on ltrim(ss.lot_id) = ltrim(sw.SMMCU)
Where sw.smactvseq='1'
and sw.SMBYR > 0
and ab.ABURRF <> ss.Customer_ID
and ss.Customer_Status = 'Buyer'
and (bu.MCRP04 = #Division_ID or #Division_ID ='All')
and (ltrim(sw.SMHBMCUS) = #Community_ID or #Community_ID ='All')
Order by JDE_DivID,JDE_CommID,JDE_LotID

Would this work for you:
update X set Update_Mode = case when X.ABURRF > 0 then 'Manually Update' else
case when #Update_Mode = '' then 'Yes/Error' else #Update_Mode
end
end
from
(
select
sw.SMACTVSEQ as JDE_ActiveRec
, sw.SMCSSEQ as JDE_SalesSeq
, bu.MCRP04 as JDE_DivID
, sw.SMHBMCUS as JDE_CommID
, cm.CMDL01 as JDE_CommunityName
, rtrim(sw.SMMCU) as JDE_LotID
, sw.SMBYR as JDE_BuyerABNo
, JDE_SSID = case
When ab.ABURRF is null then cast(0 as int)
When ab.ABURRF = '' then cast(0 as int)
else cast(ab.ABURRF as int)
end
, ss.Customer_ID as SS_CustID
, ss.Lot_ID as SS_LotID
, ss.Customer_Status as SS_CustStatus
, [dbo].[udf_ConvertJDEdate](sw.SMCDJ) as JDE_DateClosed
, ab.ABURRF
, '' as Update_Mode
--, case when ab.ABURRF >0 then 'Manually Update'
-- else
-- case when #Update_Mode ='Yes' then
-- 'Yes/Error'
-- /* **************
-- Replace 'Yes/Error' with procedure to update
-- JDE_F0101_ABURRF and return 'Yes' or 'Error'
-- ************** */
-- else #Update_Mode
-- end
-- end as Update_Mode
from [dbo].[crp_F44H501] sw
left outer join [dbo].[crp_F44H101] cm on cm.[CMHBMCUS]=sw.smhbmcus and cm.[CMCPHASE]=sw.[SMCPHASE]
left outer join [dbo].[crp_F0006] bu on bu.mcmcu = sw.smmcu
left outer join [dbo].[stg_F0101] ab on ab.aban8 = sw.SMBYR
left outer join (select distinct(lot_id),customer_ID,customer_status from [dbo].[SS_FactDemographic]) ss on ltrim(ss.lot_id) = ltrim(sw.SMMCU)
Where sw.smactvseq='1'
and sw.SMBYR > 0
and ab.ABURRF <> ss.Customer_ID
and ss.Customer_Status = 'Buyer'
and (bu.MCRP04 = #Division_ID or #Division_ID ='All')
and (ltrim(sw.SMHBMCUS) = #Community_ID or #Community_ID ='All')
) X
--Order by JDE_DivID
--, JDE_CommID
--, JDE_LotID
Remember, the #Update_Mode variable has to be declared before running this update, else you will get an error.

Related

SQL Server : using one Select statement with 2 conditions

I have the following SQL query, and I would need it to run SELECT statement only once.
May I know what are the changes I should make?
EDIT: Need to change to use only one SELECT statement..
DECLARE
#lang varchar(2) ='en',
#hideInactiveCompany integer = 0
IF #hideInactiveCompany = 1
SELECT <all columns>
FROM Config.BusinessUnit BU
LEFT JOIN Config.Organization CO on BU.OrganizationId = CO.OrganizationId
LEFT JOIN Config.ParentBusinessUnit PBU on BU.ParentBusinessUnitId = PBU.ParentBusinessUnitId
WHERE BU.IsActive = 1 --the additional condition if #hideInactiveCompany=1
ORDER BY CASE WHEN #lang = 'cn' THEN BU.Lang END,
CASE WHEN #lang = 'en' THEN BU.Lang END DESC,
EntityName
ELSE
SELECT <all columns>
FROM Config.BusinessUnit BU
LEFT JOIN Config.Organization CO on BU.OrganizationId = CO.OrganizationId
LEFT JOIN Config.ParentBusinessUnit PBU on BU.ParentBusinessUnitId = PBU.ParentBusinessUnitId
ORDER BY CASE WHEN #lang = 'cn' THEN BU.Lang END,
CASE WHEN #lang = 'en' THEN BU.Lang END DESC,
EntityName
If #hideInactiveCompany = 1, display output with BU.IsActive =1
If #hideInactiveCompany = 0, display output without BU.IsActive
filter.
We can try writing the following WHERE clause:
WHERE
(hideInactiveCompany = 1 AND BU.IsActive IS NOT NULL) OR
(hideInactiveCompany IS NULL AND BU.IsActive IS NULL) OR
(hideInactiveCompany <> 1)
Note: The OP has since changed the question a few times after I answered. The latest answer appears to be this:
WHERE
(hideInactiveCompany = 1 AND BU.IsActive = 1) OR
hideInactiveCompany IS NULL OR hideInactiveCompany <> 1
If i do understand your requirement correctly, the entire query should have only one single SELECT clause
DECLARE
#lang varchar(2) ='en',
#hideInactiveCompany integer = 0
SELECT <all columns>
FROM Config.BusinessUnit BU
LEFT JOIN Config.Organization CO on BU.OrganizationId = CO.OrganizationId
LEFT JOIN Config.ParentBusinessUnit PBU on BU.ParentBusinessUnitId = PBU.ParentBusinessUnitId
WHERE (#hideInactiveCompany = 1 AND BU.IsActive = 1)
OR (#hideInactiveCompany <> 1)
ORDER BY CASE WHEN #lang = 'cn' THEN BU.Lang END,
CASE WHEN #lang = 'en' THEN BU.Lang END DESC,
EntityName
Explanation on WHERE
Basically there are only 2 conditions:-
Condition 1 : #hideInactiveCompany = 1 AND BU.IsActive = 1
Condition 2 : #hideInactiveCompany <> 1
Condition 1 is as what you specified. When variable #hideInactiveCompany is 1, IsActive must be 1
Condition 2 is when variable #hideInactiveCompany not equal to 1
You cannot do such a "conditionally build my select" in SQL. You need to write the complete select query twice, one for each branch of the if.
(SQL is generally not a "composable" langauge, you cannot freely combine the elements how you want.)
You might be able to use case and other expressions to rebuild in a single query, or doing the common part of the query into a temporary table (or table valued variable) and then only the final part twice.
Use IF ELSE condition:
ALTER PROCEDURE [Config].[usp_ListBusinessUnit]
#lang VARCHAR(2) = NULL,
#hideInactiveCompany INTEGER
AS
BEGIN
IF #hideInactiveCompany=1
SELECT <all columns>
FROM Config.BusinessUnit BU
LEFT JOIN Config.Organization CO ON BU.OrganizationId = CO.OrganizationId
LEFT JOIN Config.ParentBusinessUnit PBU ON BU.ParentBusinessUnitId =
PBU.ParentBusinessUnitId
WHERE BU.IsActive IS NOT NULL
ORDER BY
CASE WHEN #lang = 'cn' THEN BU.Lang END,
CASE WHEN #lang = 'en' THEN BU.Lang END DESC,
EntityName
ELSE
SELECT <all columns>
FROM Config.BusinessUnit BU
LEFT JOIN Config.Organization CO ON BU.OrganizationId = CO.OrganizationId
LEFT JOIN Config.ParentBusinessUnit PBU ON BU.ParentBusinessUnitId =
PBU.ParentBusinessUnitId
WHERE BU.IsActive IS NULL
ORDER BY
CASE WHEN #lang = 'cn' THEN BU.Lang END,
CASE WHEN #lang = 'en' THEN BU.Lang END DESC,
EntityName
END

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.

Updating multiple columns for each record from table with multiple records for each ID

This is my first time posting a question here so please be gentle, I searched as exhaustively as I could. Sometimes it's how to search for the answer that is half the battle.
What I'm trying to do is update Table 1 with the data from Table 2 for each person for each period. Some people will have category A,B, and/or C records in Table 2, but not all and not necessarily all three.
The problem I'm running into is that my statement I'm using to do the update will update some of the columns but not all. I'm guessing this is because the updates weren't committed yet while doing the update so it can't fetch values that haven't been committed yet.
Do I need to do 3 separate update statements or can this somehow be handled through a case statement. I'm looking for most efficient methods here. Updating Table 1 who has 2 million records for each period.
Table 1 - Period_Perf
CustID
Period_Date
Perf_Cat_A
Perf_Cat_B
Perf_Cat_C
Table 2 - Period_Perf_Detail
CustID
Period_Date
Perf_Category (will contain A, B, or C)
Perf_Points (will contain a integer value)
Here's essentially the statement I've been trying to use:
UPDATE
Period_Perf
SET
Perf_Cat_A = CASE WHEN pd.Perf_Category = 'A' then pd.Total_Perf_Points else Perf_Cat_A END
Perf_Cat_B = CASE WHEN pd.Perf_Category = 'B' then pd.Total_Perf_Points else Perf_Cat_B END
Perf_Cat_C = CASE WHEN pd.Perf_Category = 'C' then pd.Total_Perf_Points else Perf_Cat_C END
from
Period_Perf
ON
INNER JOIN
(
select
CustID
,Period_Date
,Perf_Category
,sum(Perf_Points) as Total_Perf_Points
from
Period_Perf_Detail
group by CustID, Period_Date, Perf_Category
) as pd
ON
Period_Perf.CustID = pd.CustID and Period_Perf.Period_Date = pd.Period_Date
To update all the values at once, you'll need to have data that has all those three values in one row, so something like this:
UPDATE P
SET
Perf_Cat_A = pd.Cat_A,
Perf_Cat_B = pd.Cat_B,
Perf_Cat_C = pd.Cat_C
from
Period_Perf P
cross apply (
select
sum(case when Perf_Category = 'A' then Perf_Points else 0 end) as Cat_A,
sum(case when Perf_Category = 'B' then Perf_Points else 0 end) as Cat_B,
sum(case when Perf_Category = 'C' then Perf_Points else 0 end) as Cat_C
from
Period_Perf_Detail D
where
D.CustID = P.CustID and
D.Period_Date = P.Period_Date
) as pd
I haven't tested this, but hopefully there's no bugs.
Use SELECT statements first to understand your data, then build an update based on that select statement.
First use the following query to better understand why your update statement is not producing your desired results.
SELECT CASE WHEN pd.Perf_Category = 'A' THEN pd.Total_Perf_Points ELSE Perf_Cat_A END AS Perf_Cat_A
, CASE WHEN pd.Perf_Category = 'B' THEN pd.Total_Perf_Points ELSE Perf_Cat_B END AS Perf_Cat_B
, CASE WHEN pd.Perf_Category = 'C' THEN pd.Total_Perf_Points ELSE Perf_Cat_C END AS Perf_Cat_C
FROM Period_Perf
ON
INNER JOIN
(
SELECT CustID
, Period_Date
, Perf_Category
, SUM(Perf_Points) AS Total_Perf_Points
FROM Period_Perf_Detail
GROUP BY CustID
, Period_Date
, Perf_Category ) AS pd
ON Period_Perf.CustID = pd.CustID
AND Period_Perf.Period_Date = pd.Period_Date
I suggest the following query for your update.
UPDATE Period_Perf
SET Perf_Cat_A = SUM(a.Perf_Points)
, Perf_Cat_B = SUM(b.Perf_Points)
, Perf_Cat_C = SUM(c.Perf_Points)
FROM Period_Perf
LEFT JOIN Period_Perf_Detail AS a
ON Period_Perf.CustID = a.CustID
AND Period_Perf.Period_Date = a.Period_Date
AND a.Perf_Category = 'A'
LEFT JOIN Period_Perf_Detail AS b
ON Period_Perf.CustID = b.CustID
AND Period_Perf.Period_Date = b.Period_Date
AND a.Perf_Category = 'B'
LEFT JOIN Period_Perf_Detail AS c
ON Period_Perf.CustID = c.CustID
AND Period_Perf.Period_Date = c.Period_Date
AND a.Perf_Category = 'C'
GROUP BY Period_Perf.CustID , Period_Perf.Period_Date
Please notice that instead putting criteria in a WHERE, it is in the join itself. This way you don't affect the entire dataset, but just the subsets individually on each join.

Select Case determines Exit code or run Update statement

Trying to get the select case statement to control whether nothing happens or a table is updated based on the sum of three fields from two different tables. One of the tables is a temp table (#tempGLsum). This holds the id field and the sum amount. The "amt" field in the tblPcardGL table should never go below 0 (zero). If it would, then the flow should stop. If it will still be > 0, then the next block of code would run, which updates the tblPcardGL table.
Any assistance would be appriciated!
Thanks
declare #glID int
create table #tempGLsum
(glID int, sumAmt decimal(18,2))
insert into #tempGLsum
(glID, sumAmt)
select tblPcardReclass.glID,
sum(tblPcardReclass.reclassAmt)
from tblPcardReclass
where tblPcardReclass.glID = #glID
group by tblPcardReclass.glID
select
case when (tblPcardGL.orgAmt - tblPcardGL.amt - #tempGLsum.sumAmt) < 0
then 'stop here and let the user know it's below zero'
else
'run the code_below'
end
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
-- code_below
update tblPcardGL
set amt =
(
select
case (select COUNT(*) as numRecs from #tempGLsum)
when 0 then
tblPcardGL.orgAmt
else
(tblPcardGL.orgAmt - #tempGLsum.sumAmt)
end
)
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
You can't really do what you want with a case statement. You just have to do it in two steps:
First run the select with a where clause to show the user all the problems:
select tblPcardGL.*, 'Below Zero!' Error
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
and (tblPcardGL.orgAmt - tblPcardGL.amt - #tempGLsum.sumAmt) < 0
Then do the update with another where clause:
update tblPcardGL
set amt =
(
select
case (select COUNT(*) as numRecs from #tempGLsum)
when 0 then
tblPcardGL.orgAmt
else
(tblPcardGL.orgAmt - #tempGLsum.sumAmt)
end
)
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
and (tblPcardGL.orgAmt - tblPcardGL.amt - #tempGLsum.sumAmt) >= 0
You should consider wrapping all your #tempGLsum.sumAmt fields in isnull(#tempGLsum.sumAmt,0) because you used a left join so that column might evaluate to null, which will make any expression it is in become null.

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

Resources