rwheeler23
asked on
SQL syntax needed to convert select with join in to an update statement
I have recently discovered that on a few quotes the total of the sell price on the quote header does not equal the total of the sell prices from the lines. Is it possible to turn this select statement into an update statement where CSTQUTHD.TOT_SELL_PRC = SUM(CSTQUTLN.TOT_SELL_PRC) ?
SELECT T1.QUOTE_NUMBER,T1.SEQUENC E_NUMBER,T 1.REVALIDA TE_NUMB,T1 .TOTAL_SEL L_PRC,T2.T OTAL_SELL_ PRC
FROM (
SELECT QUOTE_NUMBER_OEQH AS QUOTE_NUMBER,SEQUENCE_NUMB ER_OEQH AS SEQUENCE_NUMBER,REVALIDATE _NUMB_OEQH AS REVALIDATE_NUMB,TOTAL_SELL _PRC_OEQH AS TOTAL_SELL_PRC
FROM CSTQUTHD ) T1
INNER JOIN (
SELECT QUOTE_NUMBER_OEQL AS QUOTE_NUMBER,SEQUENCE_NUMB ER_OEQL AS SEQUENCE_NUMBER,REVALIDATE _NUMB_OEQL AS REVALIDATE_NUMB,SUM(QUOTE_ QUANTITY_O EQL*QUOTE_ SELL_PRIC_ OEQL) AS TOTAL_SELL_PRC
FROM CSTQUTLN
GROUP BY QUOTE_NUMBER_OEQL,SEQUENCE _NUMBER_OE QL,REVALID ATE_NUMB_O EQL ) T2 ON T1.QUOTE_NUMBER=T2.QUOTE_N UMBER AND T1.SEQUENCE_NUMBER=T2.SEQU ENCE_NUMBE R AND T1.REVALIDATE_NUMB=T2.REVA LIDATE_NUM B
WHERE ROUND(T1.TOTAL_SELL_PRC,2) <>ROUND(T2 .TOTAL_SEL L_PRC,2)
SELECT T1.QUOTE_NUMBER,T1.SEQUENC
FROM (
SELECT QUOTE_NUMBER_OEQH AS QUOTE_NUMBER,SEQUENCE_NUMB
FROM CSTQUTHD ) T1
INNER JOIN (
SELECT QUOTE_NUMBER_OEQL AS QUOTE_NUMBER,SEQUENCE_NUMB
FROM CSTQUTLN
GROUP BY QUOTE_NUMBER_OEQL,SEQUENCE
WHERE ROUND(T1.TOTAL_SELL_PRC,2)
ASKER
The combination of quote,sequence and revalidate identify each document. I now need to update the CSTQUTHD.TOTAL_SELL_PRC_OE QH to the matching SUM(CSTQUTLN.QUOTE_QUANTIT Y_OEQL*QUO TE_SELL_PR IC_OEQL) value. What would the update statement look like? We have hundreds of those of the headers records and less than 1/10th of 1% have this issue. I want to fix them first and then figure out what is causing the difference.
SELECT T1.QUOTE_NUMBER,T1.SEQUENC E_NUMBER,T 1.REVALIDA TE_NUMB,T1 .TOTAL_SEL L_PRC,T2.T OTAL_SELL_ PRC
,SUM(T2.TOTAL_SELL_PRC) OVER (PARTITION BY T1.QUOTE_NUMBER, T1.SEQUENCE_NUMBER,T1.REVA LIDATE_NUM B) AS CSTQUTLN_TOT_SELL_PRC
FROM (
SELECT QUOTE_NUMBER_OEQH AS QUOTE_NUMBER,SEQUENCE_NUMB ER_OEQH AS SEQUENCE_NUMBER,REVALIDATE _NUMB_OEQH AS REVALIDATE_NUMB,TOTAL_SELL _PRC_OEQH AS TOTAL_SELL_PRC
FROM CSTQUTHD ) T1
INNER JOIN (
SELECT QUOTE_NUMBER_OEQL AS QUOTE_NUMBER,SEQUENCE_NUMB ER_OEQL AS SEQUENCE_NUMBER,REVALIDATE _NUMB_OEQL AS REVALIDATE_NUMB,SUM(QUOTE_ QUANTITY_O EQL*QUOTE_ SELL_PRIC_ OEQL) AS TOTAL_SELL_PRC
FROM CSTQUTLN
GROUP BY QUOTE_NUMBER_OEQL,SEQUENCE _NUMBER_OE QL,REVALID ATE_NUMB_O EQL ) T2 ON T1.QUOTE_NUMBER=T2.QUOTE_N UMBER AND T1.SEQUENCE_NUMBER=T2.SEQU ENCE_NUMBE R AND T1.REVALIDATE_NUMB=T2.REVA LIDATE_NUM B
WHERE ROUND(T1.TOTAL_SELL_PRC,2) <>ROUND(T2 .TOTAL_SEL L_PRC,2)
SELECT T1.QUOTE_NUMBER,T1.SEQUENC
,SUM(T2.TOTAL_SELL_PRC) OVER (PARTITION BY T1.QUOTE_NUMBER, T1.SEQUENCE_NUMBER,T1.REVA
FROM (
SELECT QUOTE_NUMBER_OEQH AS QUOTE_NUMBER,SEQUENCE_NUMB
FROM CSTQUTHD ) T1
INNER JOIN (
SELECT QUOTE_NUMBER_OEQL AS QUOTE_NUMBER,SEQUENCE_NUMB
FROM CSTQUTLN
GROUP BY QUOTE_NUMBER_OEQL,SEQUENCE
WHERE ROUND(T1.TOTAL_SELL_PRC,2)
I'd think you would just reference that field as it has been already been calculated in your derived table T2. So you'd have the following:
You would then reference the additional field (no formula required): CSTQUTHD_TOTAL_SELL_PRC_OE QH
SELECT T1.QUOTE_NUMBER,T1.SEQUENCE_NUMBER,T1.REVALIDATE_NUMB,T1.TOTAL_SELL_PRC,T2.TOTAL_SELL_PRC
,SUM(T2.TOTAL_SELL_PRC) OVER (PARTITION BY T1.QUOTE_NUMBER, T1.SEQUENCE_NUMBER,T1.REVALIDATE_NUMB) AS CSTQUTLN_TOT_SELL_PRC
,T2.TOTAL_SELL_PRC AS CSTQUTHD_TOTAL_SELL_PRC_OEQH
FROM (
SELECT QUOTE_NUMBER_OEQH AS QUOTE_NUMBER,SEQUENCE_NUMBER_OEQH AS SEQUENCE_NUMBER,REVALIDATE_NUMB_OEQH AS REVALIDATE_NUMB,TOTAL_SELL_PRC_OEQH AS TOTAL_SELL_PRC
FROM CSTQUTHD ) T1
INNER JOIN (
SELECT QUOTE_NUMBER_OEQL AS QUOTE_NUMBER,SEQUENCE_NUMBER_OEQL AS SEQUENCE_NUMBER,REVALIDATE_NUMB_OEQL AS REVALIDATE_NUMB,SUM(QUOTE_QUANTITY_OEQL*QUOTE_SELL_PRIC_OEQL) AS TOTAL_SELL_PRC
FROM CSTQUTLN
GROUP BY QUOTE_NUMBER_OEQL,SEQUENCE_NUMBER_OEQL,REVALIDATE_NUMB_OEQL ) T2 ON T1.QUOTE_NUMBER=T2.QUOTE_NUMBER AND T1.SEQUENCE_NUMBER=T2.SEQUENCE_NUMBER AND T1.REVALIDATE_NUMB=T2.REVALIDATE_NUMB
WHERE ROUND(T1.TOTAL_SELL_PRC,2)<>ROUND(T2.TOTAL_SELL_PRC,2)
You would then reference the additional field (no formula required): CSTQUTHD_TOTAL_SELL_PRC_OE
ASKER
OK, I will attempt to turn this into an update statement. Most of the work is already done.
Okay. Not sure why it would need to be turned into an update statement since the result set that it returns should provide the information you would need. But, I'm not clear if you have more going on that I'm not aware of, so I'll leave it to your discretion (just thought I'd point it out to you).
ASKER
The value on the header record needs to be corrected. There are reports that are run that use only the header table. These then get compared to reports that run only off the detail records. The results need to be the same for both.
Okay, thanks for the clarification!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Excellent. Thank you. From a performance perspective, is there any difference between doing this with partitions versus group by? I have always used group by but I see why partitioning works.
I like to use partitioning when I have multiple levels of grouping (which it allows you to do). Also, if you have a large column list and you are doing a SUM() on one of the columns, it typically makes for cleaner code. If you want to display 20 columns, but have a SUM() on Sales, and group on SalesDate, you don't have to have the other 19 columns in a GROUP BY statement. Using the window function and partitioning on only one column (SalesDate) is much more efficient to SQL Server than doing a GROUP BY on 20 columns.
ASKER
Thanks for your help folks.
Something like
Open in new window
You would then reference the additional field (no formula required): CSTQUTLN_TOT_SELL_PRC