MySQL的解决方法,它们不能一起工作 - ROWNUM

时间:2016-03-16 16:37:05

标签: mysql sql

目标是迭代表中的所有行,并根据ext_cost的总和更新每行的summary_total,其中ticket值等于当前行的票证值。可能是一个简单的语法问题或与我的MySQL版本不兼容 - 检查......有什么想法吗?

DROP PROCEDURE IF EXISTS TOTALCALC;  
DELIMITER $  
CREATE PROCEDURE TOTALCALC( IN _OFFSET INTEGER ) -- procedure with offset parameter to use like Oracle's rownum...  

BEGIN  
DECLARE n INT DEFAULT 0;  -- declare total row count variable  
DECLARE i INT DEFAULT 0;  -- set count up variable  
SELECT COUNT(*) FROM table INTO n;  -- set total row count variable  
SET i=0; -- initial count up number, may be redundant  

WHILE i<n DO -- do while counting up to total row count:  
PREPARE STMT FROM 'SELECT TICKET:=@t FROM table LIMIT ?,1'; -- set ticket variable from current row using prepared statement to allow offset variable in place of rownum (workaround)  
SET i = i + 1; -- count up toward total row count  
SET @OFFSET = _OFFSET;  
EXECUTE STMT USING @OFFSET;  
SET @OFFSET = @OFFSET + 1; -- next row  
UPDATE table SET table.SUMMARY_TOTAL = (select * from (select sum(EXT_COST) from table where TICKET = @t) AS X) WHERE TICKET = @t; -- nested subquery workaround to update using/including data selected from same table  
DEALLOCATE PREPARE STMT;  
END WHILE;  

END $  

DELIMITER ;  
CALL TOTALCALC(0); -- run starting at offset 0, which is row 1

2 个答案:

答案 0 :(得分:0)

为什么你不能使用join

update t join
       (select ticket, sum(ext_cost) as sum_ext_cost
        from t
        group by ticket
       ) tt
       on t.ticket = tt.ticket
    set t.summary_total = tt.sum_ext_cost;

这实际上看起来很尴尬,而且是一个坏主意。你有一个tickets表,每张票有一行吗?如果是这样,摘要应该放在该表中,您只需使用join获取它。

答案 1 :(得分:0)

抛开关于表格设计的讨论,以及为什么一组行的summary_cost存储在每一行中......

处理RBAR(通过痛苦的行排)是一种SQL反模式。

对于&#34; set&#34;我们通常会更好地使用SQL思维。数据的。我们不是处理单个行,而是处理一组行。

程序的整个过程看起来根本就是错误的。除了重复使用SELECT ... LIMIT n,1而没有ORDER BY子句之类的问题之外,每次运行时依赖MySQL以相同的顺序返回行,并且在过程运行时依赖于没有插入或删除行。

很难弄清楚该程序究竟应该做什么。这很难破译,我怜悯不得不坚持下去的那个不幸的灵魂。

如果该过程的目标是为表中的行组计算summary_cost,并将计算出的summary_cost分配给该组中每行的列...

使用单个SQL语句可以更清楚地完成这一点。

首先,我们写一个SELECT语句,如下所示:

SELECT t.id
     , t.ticket 
     , t.summary_cost AS old_summary_cost
     , s.summary_cost AS new_summary_cost
  FROM table t   
  JOIN ( SELECT r.*
           FROM ( SELECT q.ticket 
                       , SUM(q.ext_cost) AS summary_total
                    FROM table q
                   GROUP BY q.ticket
                 ) r
       ) s
    ON s.ticket = t.ticket

这样做的目的是返回我们想要更新的行,以及我们想要分配给summary_cost的新值。

如果有些行不应该更新,或者我们只想更新特定的行,我们可以在WHERE子句中添加适当的谓词。我们修改该查询,直到它返回我们想要更新的行,以及我们要分配的新值。

一旦我们得到SELECT语句,并且我们对结果感到满意,那么我们才会将其转换为UPDATE语句。

(您可以指出MySQL中有关从同一语句中正在更新的表中进行选择的限制,以及使用其他内联视图包装器的解决方法。我们在编写{时考虑到这一限制{1}}陈述。)

我们只需将SELECT替换为SELECT ... FROM关键字,然后添加UPDATE子句(如果有SET子句,则添加WHERE子句。)

我们最终得到:

UPDATE table t   
  JOIN ( SELECT r.*
           FROM ( SELECT q.ticket 
                       , SUM(q.ext_cost) AS summary_total
                    FROM table q
                   GROUP BY q.ticket
                 ) r
       ) s
   SET t.summary_total = s.summary_total
    ON t.ticket = s.ticket