我尝试创建一个函数,它返回第n行的摘要,其中n由查询结果的顺序定义。 这就是我所拥有的:
CREATE DEFINER=`root`@`localhost` FUNCTION `fn_inventory_stock_on_note`( fIngredient int, fInventory int, fNote int ) RETURNS float
DETERMINISTIC
BEGIN
DECLARE tStock float;
DECLARE tNoteRow int;
DECLARE tDummy int;
DECLARE rStock float;
DECLARE rRow int;
SET tNoteRow = 0;
SET @rRow := 0;
SELECT @rRow := @rRow + 1, b.ID
INTO tNoteRow, tDummy
FROM fn_inventory_book b
LEFT JOIN fn_inventory_book_in bi ON b.id = bi.bookid
LEFT JOIN fn_inventory_book_out bo ON b.id = bo.bookid
LEFT JOIN fn_dict_transactions t ON b.transactionid = t.id
WHERE b.inventoryid = fInventory
AND ( bi.ingredientid = fIngredient OR bo.ingredientid = fIngredient )
HAVING b.ID = fNote
ORDER BY b.date ASC, t.direction ASC;
SET @rRow := 0;
SET @rStock := 0;
SELECT rStock INTO tStock
FROM ( SELECT @rRow := @rRow + 1 as rRow, @rStock := @rStock + ifnull( if( bi.id is not null, bi.quantity, bo.quantity ), 0 ) * t.direction as rStock
FROM fn_inventory_book b
LEFT JOIN fn_inventory_book_in bi ON b.id = bi.bookid
LEFT JOIN fn_inventory_book_out bo ON b.id = bo.bookid
LEFT JOIN fn_dict_transactions t ON b.transactionid = t.id
WHERE b.inventoryid = fInventory
AND ( bi.ingredientid = fIngredient OR bo.ingredientid = fIngredient )
ORDER BY b.date ASC, t.direction ASC ) as q
WHERE rRow = tNoteRow;
RETURN tStock;
END
其中fIngredient
和fInventory
是查询过滤器的ID,而fNote
是来自fn_inventory_book
表的PK。
第一个选择在订单中获得所需的行号,工作正常。
我的问题是在第二个查询中,在子查询中创建一个具有相同过滤器和顺序的表,如第一个选择,具有相同的行号和每行的累积数量。在主查询中,我使用第一个选择中的行号过滤掉。
至少应该发生这种情况。但不是那样,当我运行这样的函数时:
select fn_inventory_stock_on_note( 1545, 18, 124167 ) as stock from dual;
它返回NULL
,但如果我使用相同的参数单独运行第二个查询,我会收到一笔金额。
但不是正确的数字,因为如果我只运行第二个查询的子查询,则行号不是按顺序排列的(1,2,3,6,7,4,5,8,9) ,10而不是1,2,3,..,10)。
我做错了什么?任何帮助将不胜感激。 请随意询问我的描述是否不清楚。
答案 0 :(得分:0)
我为我的问题找到了一个解决方案,但是如果有人有更好的解决方案,请分享,因为我不认为我的是正确的,尽管它有效。
DROP function IF EXISTS `fn_inventory_stock_on_note`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `fn_inventory_stock_on_note`( fIngredient int, fInventory int, fNote int, fItem int ) RETURNS float
DETERMINISTIC
BEGIN
DECLARE tStock float;
DECLARE tNoteRow int;
DECLARE rStock float;
DECLARE rRow int;
SET @rRow := 0;
DROP TEMPORARY TABLE IF EXISTS stock_temp;
CREATE TEMPORARY TABLE stock_temp ( num int, BookID int, ItemID int, qty float );
INSERT INTO stock_temp ( SELECT @rRow := @rRow + 1 as num, q.*
FROM ( SELECT b.id as BookID, if( bi.id is not null, bi.id, bo.id ) as ItemID,
ifnull( if( bi.id is not null, bi.quantity, bo.quantity ), 0 ) * t.direction as qty
FROM fn_inventory_book b
LEFT JOIN fn_inventory_book_in bi ON b.id = bi.bookid
LEFT JOIN fn_inventory_book_out bo ON b.id = bo.bookid
LEFT JOIN fn_dict_transactions t ON b.transactionid = t.id
WHERE b.inventoryid = fInventory
AND ( bi.ingredientid = fIngredient OR bo.ingredientid = fIngredient )
ORDER BY b.date ASC, t.direction ASC ) as q );
SELECT num INTO tNoteRow
FROM stock_temp st
WHERE st.BookID = fNote
AND st.ItemID = fItem;
SELECT sum( st.qty ) INTO tStock
FROM stock_temp st
WHERE st.num <= tNoteRow;
RETURN tStock;
END$$
DELIMITER ;