通过输入限制sql函数生成的行数

时间:2017-10-26 09:26:26

标签: mysql sql mariadb

尝试输出具有最低总损失金额(丢失*金额)的行的总和,其中输入(数量)确定所使用的行的数量,例如,输入3返回最低3行的总和。 使用MariaDB,当前代码为:

DELIMITER ++
CREATE FUNCTION TotalLoss (quantity INT) returns INT
WITH cte AS (
    SELECT
        M.lost*C.Number AS total,
        ROW_NUMBER() OVER (ORDER BY M.Lost*C.Number) AS row
    FROM Money M
    JOIN Company C
        ON M.Id = C.MId
)
SELECT SUM(total) FROM cte WHERE row = quantity;
DELIMITER ;

TABLE Money (Id, lost) has values (1, 10), (2,40), (3,90), (4,100)
Table Company (MId, Number) has values (3, 4), (1,2), (5, 1), (4,1)

给定输入2,输出将为220

由于最低的两个是(10 * 2 + 100 * 2)

1 个答案:

答案 0 :(得分:0)

如果我读得正确,你应该只能使用行号的不等式比较:

SELECT SUM(total) FROM cte WHERE row <= quantity;

例如,如果quantity3,则上述查询将汇总前三(最低)行的总数。

你从未提及在两个或两个以上的总数相关的情况下会发生什么。在这种情况下,使用排名函数而不是行号可能更有意义。

修改

如果你想在MySQL中做同样的事情,你将不得不做更多的工作,因为它不支持任何内置的行号功能(虽然它可能在以后)。为此,我们可以使用会话变量来跟踪行号:

SELECT SUM(total)
FROM
(
    SELECT
        (@rn:=@rn + 1) AS rn,
        M.lost*C.Number AS total
    FROM Money M
    INNER JOIN Company C
        ON M.Id = C.MId
    INNER JOIN (@rn:=0) t
    ORDER BY
        total
) t
WHERE
    t.rn <= 3;

这应该作为普通查询以及存储过程内部运行。如果您需要在函数内执行此操作,则可能需要实现一些精细的游标工作,因为可能不支持会话变量。它们可能不受支持的原因是,由于会话变量的值可能会发生变化,函数在给定相同输入的情况下不会始终返回相同的值。