【问题标题】:Error "result consisted of more than one row"错误“结果包含多行”
【发布时间】:2014-06-22 21:52:26
【问题描述】:

我在尝试从数字表中选择并附加一个包含前 4 条记录总和的列时出现此错误(“结果由多于一行组成”)(即,将两列中的值相加该记录以及接下来 3 条记录的列)。总计列是使用 FUNCTION 生成的。这是我的简化示例 - 首先创建并填充表格:

CREATE TABLE test.table1 (
  num1 float DEFAULT NULL,
  num2 float DEFAULT NULL
  );

INSERT INTO test.table1
  (num1, num2)
VALUES
  (2.5, 3.2),
  (1.4, 0.9),
  (1.7, 2.3),
  (2.6, 1.2);
  (3.3, 0.8);
  (2.0, 2.2);

现在,创建函数:

DROP FUNCTION IF EXISTS ADDNUM;
DELIMITER $$
CREATE FUNCTION ADDNUM (num1 float, num2 float) RETURNS float
DETERMINISTIC
READS SQL DATA
BEGIN
  DECLARE total, sum1 float;
  DECLARE maxv int UNSIGNED DEFAULT 4;
  DECLARE i int UNSIGNED DEFAULT 0;

  WHILE i < maxv DO
    SELECT (num1 + num2) INTO sum1 FROM table1;
     SET total = total + sum1;
    SET i = i + 1;
  END WHILE;

  RETURN (total);
END
$$

当我在 SELECT 语句中调用该函数时,出现上述错误。

SELECT num1, num2, addnum(t.num1, t.num2) AS 'Sum' FROM table1 t;

任何想法如何解决这个问题?或者也许有一种更简单的方法来实现我的最终结果。我对 MySQL 真的很陌生,所以可能从错误的角度来处理这个问题。

提前致谢!

【问题讨论】:

  • 因为您没有WHERE 子句限制为一行,也没有LIMIT。添加一个显式的ORDER BYLIMIT,OFFSET 怎么样?

标签: mysql sql


【解决方案1】:

好的,我以不同的方式解决了这个问题,最终达到了预期的结果。如果有人遇到同样的问题,这里是代码。我解决的方法是使用“动态”视图而不是循环。我不确定这是否是最优雅的做事方式,但我仍在学习,它对我有用,嘿!

1) 首先是创建表

CREATE TABLE table2 (
  DateT date DEFAULT NULL,
  HTeam varchar(255) DEFAULT NULL,
  ATeam varchar(255) DEFAULT NULL,
  HScore int(10) UNSIGNED DEFAULT NULL,
  AScore int(10) UNSIGNED DEFAULT NULL
) ENGINE = INNODB;

2) 填充数据

INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-01', 'T1', 'T2', 1, 0);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-01', 'T3', 'T4', 2, 1);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-08', 'T2', 'T3', 2, 2);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-08', 'T4', 'T1', 0, 2);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-15', 'T1', 'T3', 3, 1);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-15', 'T2', 'T4', 1, 2);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-22', 'T4', 'T2', 3, 2);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-22', 'T3', 'T1', 0, 0);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-29', 'T1', 'T4', 1, 1);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-03-29', 'T3', 'T2', 4, 2);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-04-05', 'T2', 'T1', 0, 2);
INSERT INTO test.table2(DateT, HTeam, ATeam, HScore, AScore) VALUES
('2014-04-05', 'T4', 'T3', 3, 1);

3) 接下来,我创建了一些函数,以后可以在视图中使用它们以使它们以“动态”方式运行。这是我在这个网站上遇到的一个小技巧:

DROP FUNCTION IF EXISTS func_hteam;
CREATE FUNCTION func_hteam() RETURNS VARCHAR(255) DETERMINISTIC
  RETURN @hteam;

DROP FUNCTION IF EXISTS func_ateam;
CREATE FUNCTION func_ateam() RETURNS VARCHAR(255) DETERMINISTIC
  RETURN @ateam;

DROP FUNCTION IF EXISTS func_datet;
CREATE FUNCTION func_datet() RETURNS date DETERMINISTIC
  RETURN @datet;

4) 接下来,我创建了一个“动态”视图:

DROP VIEW IF EXISTS view_total;
CREATE VIEW view_total (DateT, HTeam, ATeam, HScore, AScore, Total)
AS 
(SELECT DateT, HTeam, ATeam, HScore, AScore, (HScore + AScore) AS 'Sum' FROM test.table2
    WHERE (HTeam = func_hteam() OR ATeam = func_hteam()) AND DateT < func_datet()
    ORDER BY DateT DESC LIMIT 4)
UNION DISTINCT
(SELECT DateT, HTeam, ATeam, HScore, AScore, (HScore + AScore) AS 'Sum' FROM test.table2
    WHERE (HTeam = func_ateam() OR ATeam = func_ateam()) AND DateT < func_datet()
    ORDER BY DateT DESC LIMIT 4)
ORDER BY DateT DESC;

5) 接下来,我创建了一个函数来计算前一个视图返回的所有行的总和:

DROP FUNCTION IF EXISTS func_total;
DELIMITER $$
CREATE FUNCTION func_total() RETURNS int DETERMINISTIC
BEGIN
  DECLARE num int UNSIGNED DEFAULT 0;
  SELECT SUM(total) INTO num FROM view_total;
RETURN (num);
END
$$

6) 最后,将所有这些结合在一起的函数:

DROP FUNCTION IF EXISTS func_final;
DELIMITER $$
CREATE FUNCTION func_final(hteam VARCHAR(255), ateam VARCHAR(255), datet DATE) RETURNS int DETERMINISTIC
  BEGIN
    DECLARE total INT DEFAULT 0;
    SELECT func_total() INTO total
      FROM (SELECT @hteam:=hteam hteam,
                   @ateam:=ateam ateam,
                   @datet:=datet datet) t1, view_total t
      ORDER BY t.datet ASC LIMIT 1;
RETURN (total);
END
$$

7) ...现在我们得到数据:

SELECT DateT, HTeam, ATeam, HScore, AScore, func_final(HTeam, ATeam, Datet) AS TOTAL
  FROM table2 ORDER BY DateT DESC;

所有作品,可以用更好的方式编写吗?也许吧,但在这个阶段这超出了我的能力:)

美好的一天! :P

【讨论】:

  • 不知道你是否知道,但问题是“这可以用更好的方式写吗?”可能会在Code Review 上成为主题。
【解决方案2】:

错误导致

SELECT (num1 + num2) INTO sum1 FROM table1

它尝试从table1 中选择许多 行到一个 变量sum1。要解决此问题,您可以使用

limit 结果集
SELECT (num1 + num2) INTO sum1 FROM table1 limit 1

此外,你必须初始化你的变量total

declare total float default 0;

否则,它的值为NULL,见DECLARE


使用变量limitoffset的解决方案似乎是prepareexecute一个语句

prepare stmt from "select * from table1 limit ? offset ?";
execute stmt using lim, off;

另请参阅Variable LIMIT Clause in MySQLUsing variables as OFFSET in SELECT statments inside mysql's stored functions 以获得更详细的解决方案。

SP does not accept variables in LIMIT clause 上还有一个错误报告/功能请求的提示,以及分别在版本 5.5.6 和 6.0.14 中的修复,http://bugs.mysql.com/bug.php?id=11918#c328636

【讨论】:

  • 感谢 Olaf/Michael... 设法使用 LIMIT 和 OFFSET(下面的代码)从存储在变量中的每一行获取总和,但是,我仍然很难获得前 4 名的全部总数使用 WHILE 循环的行。例如top (2.5, 3.2),top 4行总数= 15.8 (1.4, 0.9),top 4行总数= 14.2 (1.7, 2.3),top 4行总数= 16.1 (2.6, 1.2); (3.3, 0.8); (2.0, 2.2);
  • DROP FUNCTION IF EXISTS ADDNUM; DELIMITER $$ CREATE FUNCTION ADDNUM (num1 float, num2 float) RETURNS float DETERMINISTIC READS SQL DATA BEGIN DECLARE total, sum1 float; DECLARE maxv int UNSIGNED DEFAULT 4; DECLARE i int UNSIGNED DEFAULT 0; WHILE i &lt; maxv DO SELECT (num1 + num2) INTO sum1 FROM table1 LIMIT i, 1; SET total = total + sum1; SET i = i + 1; END WHILE; RETURN (total); END $$ SELECT num1, num2, addnum(num1, num2) FROM table1
  • 这个赋值语句似乎有问题 SET total = total + sum1;
  • 你还没有初始化total,查看更新的答案。
  • 感谢奥拉夫,这有帮助。我现在面临的问题是我不能使用变量来设置偏移量。我需要该函数循环遍历前 4 条记录,因此我需要偏移量是动态的(即在每次循环运行时递增 1)。我使用了语句 SELECT (num1 + num2) INTO sum1 FROM table1 LIMIT 1 OFFSET i; 我将从 0 迭代到 3。这个想法是获取前 4 行的每一行的总和然后将它们加在一起。有任何想法吗?到目前为止,我非常感谢您的帮助:)
猜你喜欢
  • 2011-01-15
  • 2023-03-21
  • 2018-03-07
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 2017-03-14
  • 1970-01-01
相关资源
最近更新 更多