下面是正常工作的方法,但我如何转换它并直接在select语句中使用它来获得所需的结果。
SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS DayCount;
DELIMITER |
CREATE FUNCTION DayCount( d1 DATE, d2 DATE, daynum SMALLINT ) RETURNS INT
BEGIN
DECLARE days INT DEFAULT 0;
IF D1 IS NOT NULL AND D2 IS NOT NULL THEN
WHILE D1 <= d2 DO
BEGIN
IF DAYOFWEEK(d1) = daynum THEN
SET days=days+1;
END IF;
SET d1 = ADDDATE(d1, INTERVAL 1 DAY);
END;
END WHILE;
END IF;
RETURN days;
END;
|
DELIMITER;
SELECT(daycount(&#39; 2017-02-05&#39;,&#39; 2017-02-20&#39;,7))+(daycount(&#39; 2017-02-05&#) 39;,&#39; 2017-02-20&#39;,1))AS&#39; Weekends&#39;;
对于上述查询,我需要一种方法来传递7&amp; 1动态地能够传递非工作日并从主查询中删除那些天来计算分辨率和响应时间,但根本没有函数,直接选择语句的方式。
更新:
我在下面有一个查询,我在 closeDate 和 edate 之间计算时间,我需要排除非工作日,非工作日列表是动态,可能是1到7(星期日到星期六),我的要求是排除非工作日并通过mysql查询本身计算平均值,而不是稍后通过PHP操作:
SELECT `complains`.`id`,
DATE (edate) AS _date,
AVG((UNIX_TIMESTAMP(closeDate) - UNIX_TIMESTAMP(edate))) AS _seconds,
COUNT(*) AS totalCases
FROM `complains`
WHERE (
(`complains`.`govt_id` = '22')
AND (
`complains`.`edate` BETWEEN DATE ('2016-01-01')
AND DATE ('2017-01-01')
)
)
AND (`complains`.`status` = 2)
GROUP BY `_date`
ORDER BY `_date`
因此,必须在不同字段之间排除工作日,即 closeDate 和 edate ,其中 edate 是案例的入口日期。我基本上计算了案件的平均解决时间。
SQL小提琴 link to sql fiddle
答案 0 :(得分:1)
您可以通过聚合功能实现您想要的功能,尤其是count
:
SELECT count(*) AS dayscount
FROM table
WHERE (date BETWEEN d1 AND d2) AND DAYOFWEEK(date)=daynum
注意函数是在上面的DAYOFWEEK
函数之类的select语句中使用的东西,它们并不意味着替换select语句,反之亦然,那是因为函数不需要任何表,在上面的select语句中,我不得不放FROM table
,但在你的函数中没有特定的表。
我同意,当我们想要将某些列转换为某些内容(比如将字符串列解析为整数或获取两个日期之间的差异)时,最好不要为所需内容提供函数并定义它们。等等)。
顺便说一句count
是一个函数,特别是一个聚合函数,就像AVG
,SUM
,MAX
等,你的函数只是一个有条件的计数
关于您的更新,简短的回答是:如果不声明功能,则无法执行此操作。
用select
替换函数意味着某些表中存在数据,如果我想将工作日从edate排除到closeate那么必须存储那些工作日但它们在哪里?在什么表?为此,功能是必须的。
但是你的函数不需要做所有事情,查询可以这样写:
SELECT id,
DATE (edate) AS _date,
AVG((NONWORKDAYSCOUNT(edate,closedate,workdaysnum))) AS _seconds,
COUNT(*) AS totalCases
FROM complains
WHERE (
(govt_id = '22')
AND (
edate BETWEEN DATE ('2016-01-01')
AND DATE ('2017-01-01')
)
)
AND (status = 2)
GROUP BY _date
ORDER BY _date
我会给你留下NONWORKDAYSCOUNT,它与你拥有的DayCount差不多,但你需要将daynum
作为“类似数组”类型(mysql没有数组)传递给你,你可以看到{ {3}}问题,特别是FIND_IN_SET
是您需要的功能,DayCount
包括daynum
中传递的日期不排除它们(这是正确还是错误取决于您是否将daynum
解释为工作日或非工作日),它还需要将其结果转换为秒。
顺便说一下你提到你想用mysql而不是php来做性能,而你的情况是正确的,一般来说我们不喜欢把CPU负载放在我们的数据库上,你真的应该在判断之前测量表现。
P.S:除非您想为表提供不同的名称或者加入两个(或更多)具有共享列的表,否则每次要提及列时都不需要提及表名。
您也不需要在“``”
中包装列名