Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-03 : 14:33:21
|
| Here is the latest quandry:I wrote up this query to for the sales department, but have run into a little problem. On execution I get "subquery returned more than 1..."It is flagged for both subqueries. Does this need to be re-typed with a cursor, or is there a better way to do this?AndyThere's never enough time to type code right, but always enough time for a hotfix... |
|
|
spirit1
Cybernetic Yak Master
11752 Posts |
Posted - 2005-01-03 : 14:36:19
|
maybe you should show us the query.Go with the flow & have fun! Else fight the flow |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-03 : 14:57:49
|
Oh!What a Dumb A** I am!here we go:--- BELOW SELECTS LINES AND CALCULATES PROFIT AS A PERCENTAGE BY LINES ON AN INVOICE---BEGINDECLARE @PCT NUMERIC,@PROFIT_AMT NUMERIC,@COMMISSION NUMERICSET @PCT=(select casewhen coalesce(prc,0)=0 and coalesce(reg_prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(reg_prc,0)=0 and coalesce(cost,0)<>0then cast(((reg_prc-cost)/cost)as numeric)*100when coalesce(prc,0)=0 and coalesce(reg_prc,0)<>0 and coalesce(cost,0)<>0then cast(-((reg_prc-cost)/cost)as numeric)*100when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then (((prc-cost)/cost)*100)endFROM PS_TKT_HIST_LIN)SET @PROFIT_AMT=(SELECTcasewhen coalesce(prc,0)=0 and coalesce(reg_prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(reg_prc,0)<>0 and coalesce(cost,0)<>0then cast(-((reg_prc-cost))as numeric)when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then((prc-cost))endFROM PS_TKT_HIST_LIN)SET @COMMISSION=(SELECTCASEWHEN COALESCE (@PCT,0) BETWEEN 0 AND 20THEN 0WHEN COALESCE(@PCT,0) BETWEEN 21 AND 25THEN (@PROFIT_AMT/100)WHEN COALESCE(@PCT,0) BETWEEN 26 AND 28THEN ((@PROFIT_AMT/100)*2)WHEN COALESCE(@PCT,0)BETWEEN 29 AND 32THEN ((@PROFIT_AMT/100)*3)WHEN COALESCE(@PCT,0)>32THEN ((@PROFIT_AMT/100)*3.5)END)SELECTPS_TKT_HIST.SLS_REP,ps_tkt_hist_lin.cost,ps_tkt_hist_lin.tkt_no,ps_tkt_hist_lin.item_no, im_item.categ_cod,@PCT AS PCT,@PROFIT_AMT AS PROFIT_AMT,@COMMISSION AS COMMISSIONfrom PS_TKT_HIST RIGHT OUTER JOIN PS_TKT_HIST_LINON PS_TKT_HIST.STR_ID=PS_TKT_HIST_LIN.STR_IDAND PS_TKT_HIST.STA_ID=PS_TKT_HIST_LIN.STA_IDAND PS_TKT_HIST.TKT_NO=PS_TKT_HIST_LIN.TKT_NOjoin im_itemon ps_tkt_hist_lin.item_no=im_item.item_noand im_item.item_no<>'NOTE'and im_item.categ_cod<>'WALAB'and im_item.categ_cod<>'RELAB'END all this, and good looks, too! There's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
spirit1
Cybernetic Yak Master
11752 Posts |
Posted - 2005-01-03 : 15:01:38
|
just add those case statments to you main select instead of variables.it should do the trick.Go with the flow & have fun! Else fight the flow |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-03 : 15:24:12
|
I originally did it this way so I could do the commission amount calculation on the two variables:@commission is calsculated off of @pct and @profit_amt. If I don't do them as a variable, how can I reference them? Or am I having a mycodis crappus moment? There's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
spirit1
Cybernetic Yak Master
11752 Posts |
Posted - 2005-01-03 : 15:40:04
|
how bout:select pct*profit_amt as commission, *from (your sql here) t1Go with the flow & have fun! Else fight the flow |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-03 : 16:19:47
|
Ok,Now that you've shown me that I like to do things twice, let me explain:We need to expand thisSET @COMMISSION=(SELECTCASEWHEN COALESCE (@PCT,0) BETWEEN 0 AND 20THEN 0WHEN COALESCE(@PCT,0) BETWEEN 21 AND 25THEN (@PROFIT_AMT/100)WHEN COALESCE(@PCT,0) BETWEEN 26 AND 28THEN ((@PROFIT_AMT/100)*2)WHEN COALESCE(@PCT,0)BETWEEN 29 AND 32THEN ((@PROFIT_AMT/100)*3)WHEN COALESCE(@PCT,0)>32THEN ((@PROFIT_AMT/100)*3.5)END into about 15 different percentages. What the select is doing is first calculating the percentage of profit (The boss wants this in there, too) and then calculating the amount of commission based on the variables above. If I take out the above code, It works fine. When I add the above stuff, I get "invalid column name PCT" and invalid column name profit_amt".What am I missing?There's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-03 : 17:24:32
|
Another way to look at this:--- BELOW SELECTS LINES AND CALCULATES PROFIT AS A PERCENTAGE BY LINES ON AN INVOICE---selectcasewhen coalesce(prc,0)=0 and coalesce(reg_prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(reg_prc,0)=0 and coalesce(cost,0)<>0then cast(((reg_prc-cost)/cost)as numeric)*100when coalesce(prc,0)=0 and coalesce(reg_prc,0)<>0 and coalesce(cost,0)<>0then cast(-((reg_prc-cost)/cost)as numeric)*100when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then (((prc-cost)/cost)*100)endas pct,casewhen coalesce(prc,0)=0 and coalesce(reg_prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(reg_prc,0)<>0 and coalesce(cost,0)<>0then cast(-((reg_prc-cost))as numeric)when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then((prc-cost))endas profit_amt,PS_TKT_HIST.SLS_REP,ps_tkt_hist_lin.cost,ps_tkt_hist_lin.tkt_no,ps_tkt_hist_lin.item_no, im_item.categ_codfrom PS_TKT_HIST RIGHT OUTER JOIN PS_TKT_HIST_LINON PS_TKT_HIST.STR_ID=PS_TKT_HIST_LIN.STR_IDAND PS_TKT_HIST.STA_ID=PS_TKT_HIST_LIN.STA_IDAND PS_TKT_HIST.TKT_NO=PS_TKT_HIST_LIN.TKT_NOjoin im_itemon ps_tkt_hist_lin.item_no=im_item.item_noand im_item.item_no<>'NOTE'and im_item.categ_cod<>'WALAB'and im_item.categ_cod<>'RELAB' This works fine. How do I incorporate this:SELECTCASEWHEN COALESCE (PCT,0) BETWEEN 0 AND 20THEN 0WHEN COALESCE(PCT,0) BETWEEN 21 AND 25THEN (PROFIT_AMT/100)WHEN COALESCE(PCT,0) BETWEEN 26 AND 28THEN ((PROFIT_AMT/100)*2)WHEN COALESCE(PCT,0)BETWEEN 29 AND 32THEN ((PROFIT_AMT/100)*3)WHEN COALESCE(PCT,0)>32THEN ((PROFIT_AMT/100)*3.5)ENDAS COMMISSION Into it? If I add it to the SELECT statement I keep getting 'invalid column' errors for PCT and PROFIT_AMT. If I add it as a variable, then I think it gets more complicated than need be.WAAAH!!(I myself vote for more coffee...)There's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-04 : 10:06:40
|
| The problem here is how to deal with the divide by zero error trying to get the COMMISSION column. We need to calculate the percentage of profit, then calculate the amount of commission off of that. Since we can't use derived columns in the commission calculation( That's the invalid column error) then we need to do the calculations for commission differently. Problem is, we keep hitting divide by zero errors (salespeople love to give things out at bizarre prices apparently).SO...Anybody have any ideas about how to go about this and avoid the dreaded divide by monster?There's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
AndrewMurphy
Master Smack Fu Yak Hacker
2916 Posts |
Posted - 2005-01-04 : 10:33:32
|
| supply sample input data......and expected results....covering all situations...or even write it down for yourself and push each case through your SQL....that should help you identify the cases where you are going to hit 'div by 0'...and to write out the formula for each scenario. |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-04 : 13:13:10
|
Hey Andrew,Ok, I got the divide by zero issue sorted out. NOW I have the last piece of this puzzle to sort out.Here is the new, improved query:--- BELOW SELECTS LINES AND CALCULATES PROFIT AS A PERCENTAGE BY LINES ON AN INVOICE---select-- First we show our profit as a percentage--casewhen coalesce(prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(cost,0)<>0then ((prc-cost)/cost)*100when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then (((prc-cost)/cost)*100)endas pct,-- show the dollar amount (+ or -) of profit--casewhen coalesce(prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(cost,0)<>0then -((reg_prc-cost))when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then((prc-cost))endas profit_amt,-- THIS STATEMENT CALCULATES COMMISION--CASE-- If the selling price is zero --when coalesce(prc,0)=0 and coalesce(cost,0)<>0-- take potential sale away from commission total -- then (-(reg_prc-cost))-- if the selling price is > zero ---- an profit is 20% or less --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100)<20.00-- pay no commission --then 0-- if profit is 20.01% to 25.00% --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100) between 20.01 and 25.00-- pay 1% commission --then ((prc-cost)/100)-- if profit is 25.01% to 30.00% --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100) between 25.01 and 30.00-- pay 2% commission --then ((prc-cost)/50)-- if profit is greater than 30.01% --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100)>30.01-- pay 3% commission --then ((prc-cost)/33.33)ENDAS COMMISSION,(po_ord_hdr.ord_misc_amt_1/max(po_ord_lin.seq_no))as frt,--return our additional columns for reporting --PS_TKT_HIST.SLS_REP,ps_tkt_hist_lin.reg_prc,ps_tkt_hist_lin.cost,ps_tkt_hist_lin.prc,ps_tkt_hist_lin.tkt_no,ps_tkt_hist_lin.item_no, im_item.categ_codfrom PS_TKT_HIST RIGHT OUTER JOIN PS_TKT_HIST_LINON PS_TKT_HIST.STR_ID=PS_TKT_HIST_LIN.STR_IDAND PS_TKT_HIST.STA_ID=PS_TKT_HIST_LIN.STA_IDAND PS_TKT_HIST.TKT_NO=PS_TKT_HIST_LIN.TKT_NOjoin im_itemon ps_tkt_hist_lin.item_no=im_item.item_noright outer join po_ord_linon po_ord_lin.commnt_1=ps_tkt_hist.tkt_noright outer join po_ord_hdron po_ord_hdr.po_no=po_ord_lin.po_no-- disallow notes,labor, and extended service plans from commission --where im_item.item_no<>'NOTE'and im_item.categ_cod<>'WALAB'and im_item.categ_cod<>'RELAB'and im_item.subcat_cod<>'ESPS'group by PS_TKT_HIST_LIN.TKT_NO,PS_TKT_HIST.SLS_REP,PS_TKT_HIST_LIN.PRC,PS_TKT_HIST_LIN.COST,PS_TKT_HIST_LIN.REG_PRC,PS_TKT_HIST_LIN.ITEM_NO,im_item.CATEG_COD,po_ord_hdr.ord_misc_amt_1order by ps_tkt_hist_lin.tkt_no The frt calculation is messed up. What we have is this:each line in PS_TKT_HIST_LIN may have an associated row in PO_ORD_LIN. What we want to do is: count up the number of lines on a given PO, divide the amount of freight charges on that po (PO_ORD_HDR.ORD_MISC_AMT_1) by the number of lines on that po, and return that amount for the item. Even if I do this:select po_ord_hdr.po_no,po_ord_lin.item_no,max(po_ord_lin.seq_no) as frtfrom po_ord_hdrright outer join po_ord_linon po_ord_hdr.po_no=po_ord_lin.po_nogroup by po_ord_hdr.po_no,po_ord_lin.item_no It returns something like this:PO_NO ITEM_NO FRT-------------------123 abc 4123 def 4123 efg 2123 ghi 1123 jkl 5What we need is for frt to be all '5' in order for the divide to work. We don't really need to return this in the select; what is ultimatley needed is for the freight calculation to be subtracted from the amount of profit on each line and also from the amount we calculate profit precentage and commission on (the green fields above)AndyThere's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
AndrewMurphy
Master Smack Fu Yak Hacker
2916 Posts |
Posted - 2005-01-05 : 06:03:40
|
| 1. Can you pre-calc and save the "freight" column....ie as a stage 1 of a 2-part "calculate our profit" process??...then you can just reference it direct?...otherwise you have to calculate it as per 2 below.2. search here for running total and/or percentages....other solutions have been posted before.3. your code is grand....but what about the future? what will happen if some fancy sales director wants to change the commision rules 2/3 months down the line? he/she will need to bring you back in....(great idea for ensuring permanency!!!)....however it might be neater/better in the long run if you could put the 'commission rules' (ie thresholds + pct's) into a (properly indexed) data table to which you could 'join' your raw data to derive your desired end result....then by simply adding/amending the 'rules' you can change the end result...with no further programming.... |
 |
|
|
steamngn
Constraint Violating Yak Guru
306 Posts |
Posted - 2005-01-05 : 11:14:46
|
Ok Andrew,Check out the most recent draft:--- BELOW SELECTS LINES AND CALCULATES PROFIT AS A PERCENTAGE BY LINES ON AN INVOICE---select-- First we show our gross profit as a percentage--casewhen coalesce(prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(cost,0)<>0then ((prc-cost)/cost)*100when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then ((prc-cost)/cost)*100endas gross_pct,-- now show the net profit percentage--casewhen coalesce(prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)=0then ((prc-cost)/cost)*100when coalesce(prc,0)=0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)<>0then ((prc-(cost+((po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no)))))/cost)*100when coalesce(prc,0)<>0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)=0then ((prc-cost)/cost)*100when coalesce (prc,0)<>0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)<>0then ((prc-(cost+((po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no)))))/cost)*100endas net_pct,-- show the gross dollar amount (+ or -) of profit--casewhen coalesce(prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce(prc,0)=0 and coalesce(cost,0)<>0then -((reg_prc-cost))when coalesce (prc,0)<>0 and coalesce(cost,0)<>0then((prc-cost))endas gross_profit_amt,-- now show our net dollar amount(+ or-) of profit --casewhen coalesce(prc,0)=0 and coalesce(cost,0)=0then NULLwhen coalesce (prc,0)=0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)=0then -((reg_prc-cost))when coalesce(prc,0)=0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)<>0then -((reg_prc-cost)-(po_ord_hdr.ord_misc_amt_1/(select max (po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no)))when coalesce (prc,0)<>0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)=0then ((prc-cost))when coalesce (prc,0)<>0 and coalesce(cost,0)<>0 and coalesce(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no),0)<>0then((prc-(cost-(po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no)))))endas net_profit_amt,-- THIS STATEMENT CALCULATES COMMISSION--CASE-- If the selling price is zero --when coalesce(prc,0)=0 and coalesce(cost,0)<>0-- take potential sale away from commission total -- then (-(reg_prc-cost))-- if the selling price is > zero ---- an profit is 20% or less --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100)<20.00-- pay no commission --then 0-- if profit is 20.01% to 25.00% --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100) between 20.01 and 25.00-- pay 1% commission --then ((prc-cost)/100)-- if profit is 25.01% to 30.00% --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100) between 25.01 and 30.00-- pay 2% commission --then ((prc-cost)/50)-- if profit is greater than 30.01% --when coalesce (prc,0)<>0 and coalesce(cost,0)<>0and (((prc-cost)/cost)*100)>30.01-- pay 3% commission --then ((prc-cost)/33.33)ENDAS COMMISSION,--calculate the amount of freight per line item --'frt'=casewhen coalesce(po_ord_hdr.ord_misc_amt_1,0)<>0 and po_ord_lin.commnt_1=ps_tkt_hist.orig_ord_nothen po_ord_hdr.ord_misc_amt_1/(select max(po_ord_lin.seq_no)from po_ord_linwhere po_ord_lin.po_no=po_ord_hdr.po_no)end,--return our additional columns for reporting --po_ord_hdr.po_no,PS_TKT_HIST.SLS_REP,ps_tkt_hist_lin.reg_prc,ps_tkt_hist_lin.cost,ps_tkt_hist_lin.prc,ps_tkt_hist_lin.tkt_no,ps_tkt_hist.orig_ord_no,ps_tkt_hist_lin.item_no, im_item.categ_codfrom PS_TKT_HIST RIGHT OUTER JOIN PS_TKT_HIST_LINON PS_TKT_HIST.STR_ID=PS_TKT_HIST_LIN.STR_IDAND PS_TKT_HIST.STA_ID=PS_TKT_HIST_LIN.STA_IDAND PS_TKT_HIST.TKT_NO=PS_TKT_HIST_LIN.TKT_NOleft outer join po_ord_linon po_ord_lin.commnt_1=ps_tkt_hist.orig_ord_noand po_ord_lin.item_no=ps_tkt_hist_lin.item_noleft outer join po_ord_hdron po_ord_hdr.po_no=po_ord_lin.po_nojoin im_itemon ps_tkt_hist_lin.item_no=im_item.item_no-- disallow notes,labor, extended service plans, warranty and service tickets from commission --where ps_tkt_hist_lin.item_no<>'NOTE'and ps_tkt_hist_lin.categ_cod<>'WALAB'and ps_tkt_hist_lin.categ_cod<>'RELAB'and ps_tkt_hist_lin.subcat_cod<>'ESPS'and ps_tkt_hist.has_warr_items<>'Y'and ps_tkt_hist.is_svc_call<>'Y'group by PS_TKT_HIST_LIN.TKT_NO,PS_TKT_HIST.SLS_REP,PS_TKT_HIST_LIN.PRC,po_ord_hdr.po_no,PS_TKT_HIST_LIN.COST,PS_TKT_HIST_LIN.REG_PRC,po_ord_lin.commnt_1,PS_TKT_HIST_LIN.ITEM_NO,im_item.CATEG_COD,po_ord_hdr.ord_misc_amt_1,ps_tkt_hist.orig_ord_no,po_ord_lin.item_noorder by ps_tkt_hist_lin.tkt_no This sure is a mouthfull! This query works as requested. In actuality this will be added to a procedure, and things like commission amounts and percentage breakpoints will be definable via the app. There is much concern about being able to 'tamper' with the math (I'm not really sure why everyone is concerned, but they are) and as such want everything formatted like this. Ugly, yes. but it looks like it will do the job..AndyThere's never enough time to type code right, but always enough time for a hotfix... |
 |
|
|
|
|
|
|
|