2

我对 MySQL 中的存储函数有一个非常令人沮丧的问题。我有一个数据库,其中包含来自连接到无线热点的用户的会话数据。我正在尝试从选定月份内选择单个用户下载统计信息。我的问题是函数中的子查询似乎忽略mac了 WHERE 语句中的字段。这是我的代码:

CREATE FUNCTION get_month_download(mo varchar(45), box int(11), mac varchar(45))   RETURNS DOUBLE
BEGIN
    DECLARE dwnld double;
    IF mo IS NULL THEN
        SET mo := CONCAT(CONCAT(YEAR(NOW()), '-', MONTH(NOW())),'-','01');
    END IF;
    SET dwnld := (
        SELECT SUM(`tx_bytes`) 
        FROM `session` 
        WHERE `assoc_time` > UNIX_TIMESTAMP(mo) 
        AND `disassoc_time` < UNIX_TIMESTAMP(DATE_ADD(mo, INTERVAL 1 MONTH))
        AND `mac` = mac
        AND `controller_id` = box
    );
    return dwnld;
END

运行这个:

SELECT get_month_download('2012-09-01', '2', '00:21:5c:56:be:a3');

返回整个表的下载数据,尽管它使用controller_id过滤数据。

如果我使用相同的参数在函数外部运行子查询,它工作正常。是什么赋予了?

更清楚地说,运行这个查询:

SELECT SUM(`tx_bytes`) 
FROM `session` 
WHERE `assoc_time` > UNIX_TIMESTAMP('2012-09-01') 
AND `disassoc_time` < UNIX_TIMESTAMP(DATE_ADD('2012-09-01', INTERVAL 1 MONTH))
AND `mac` = '00:21:5c:56:be:a3'
AND `controller_id` = '2';

返回该用户的正确下载统计信息。该函数返回该控制器的所有用户的统计信息。

4

2 回答 2

1

你确定有不止一份controller_id礼物吗?

SELECT DISTINCT controller_id FROM session

此查询获取了多少条记录?

如果这只获取一条记录,并且对应于 box = 2,则没有问题。

如果有多个控制器 ID,请运行此查询,

SELECT COUNT(1), controller_id 
FROM session 
WHERE assoc_time > '2012-01-01' 
AND disassoc_time < '2012-01-31'
AND mac = '00:21:5c:56:be:a3'
GROUP BY controller_id

这会返回多少行?如果它只返回一个 controller_id 2 的记录,则没有任何问题。

于 2013-01-24T15:51:07.467 回答
1

我真的应该更经常地反思我的老师在大学里教给我的东西。问题是在 select 语句的范围内,变量mac被视为表中的一个字段,而不是函数中的我的参数。因此,更改参数名称解​​决了这个问题:

CREATE FUNCTION get_month_download(mo varchar(45), box int(11), inmac varchar(60)) RETURNS DOUBLE 
BEGIN  
    DECLARE dwnld double;
    IF mo IS NULL THEN
        SET mo := CONCAT(CONCAT(YEAR(NOW()), '-', MONTH(NOW())),'-','01');
    END IF;
    SET dwnld := (
        SELECT SUM(`tx_bytes`)   
        FROM `session`    
        WHERE `assoc_time` > UNIX_TIMESTAMP(mo)    
        AND `disassoc_time` < UNIX_TIMESTAMP(DATE_ADD(mo, INTERVAL 1 MONTH))      
        AND `controller_id` = box
        AND `mac` = inmac
    );
     return dwnld; 
END

这是一个“打脸”的时刻。感谢大家的帮助。

于 2013-01-24T16:46:58.437 回答