SQL syntax needed to convert select with join in to an update statement

rwheeler23
rwheeler23 used Ask the Experts™
on
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.SEQUENCE_NUMBER,T1.REVALIDATE_NUMB,T1.TOTAL_SELL_PRC,T2.TOTAL_SELL_PRC
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)
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2008

Commented:
If this is being pulled from a SQL Server you could use PARTITION BY to create a field for each row record that would contain the total value you are looking for a particular QUOTE_NUMBER

Something like

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) AS CSTQUTLN_TOT_SELL_PRC
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) 

Open in new window


You would then reference the additional field (no formula required): CSTQUTLN_TOT_SELL_PRC
rwheeler23President

Author

Commented:
The combination of quote,sequence and revalidate identify each document. I now need to update the CSTQUTHD.TOTAL_SELL_PRC_OEQH to the matching SUM(CSTQUTLN.QUOTE_QUANTITY_OEQL*QUOTE_SELL_PRIC_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.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
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)
Top Expert 2008

Commented:
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:

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) 

Open in new window


You would then reference the additional field (no formula required): CSTQUTHD_TOTAL_SELL_PRC_OEQH
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

rwheeler23President

Author

Commented:
OK, I will attempt to turn this into an update statement. Most of the work is already done.
Top Expert 2008

Commented:
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).
rwheeler23President

Author

Commented:
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.
Top Expert 2008

Commented:
Okay, thanks for the clarification!
Database Developer
Commented:
This should do the update:
UPDATE    HDR
SET       TOTAL_SELL_PRC_OEQH = UPD.TOTAL_SELL_PRC
FROM      CSTQUTHD HDR
INNER JOIN 
        (
        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
        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)
        ) UPD
ON     HDR.QUOTE_NUMBER_OEQH = UPD.QUOTE_NUMBER
AND    HDR.SEQUENCE_NUMBER_OEQH = UPD.SEQUENCE_NUMBER
AND    HDR.REVALIDATE_NUMB_OEQH = UPD.REVALIDATE_NUMB;

Open in new window

rwheeler23President

Author

Commented:
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.
Doug BishopDatabase Developer

Commented:
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.
rwheeler23President

Author

Commented:
Thanks for your help folks.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial