在MySQL中将行限制为列的和等于某个值
我想编写一个查询,返回所有行,直到其中一列值的总和达到某个值 如下表所示:在MySQL中将行限制为列的和等于某个值,mysql,sql,Mysql,Sql,我想编写一个查询,返回所有行,直到其中一列值的总和达到某个值 如下表所示: DATE ETC Meeting 2013-02-01 00:00:00 85482 1 2013-02-01 00:00:00 47228 2 2013-02-02 00:00:00 12026 4 2013-02-03 00:00:00 78927 6
DATE ETC Meeting
2013-02-01 00:00:00 85482 1
2013-02-01 00:00:00 47228 2
2013-02-02 00:00:00 12026 4
2013-02-03 00:00:00 78927 6
2013-02-04 00:00:00 85662 2
2013-03-05 00:00:00 47978 1
2013-08-07 00:00:00 8582 1
如果我想得到行,直到列集合的和等于7
DATE ETC Meeting
2013-02-01 00:00:00 85482 1
2013-02-01 00:00:00 47228 2
2013-02-02 00:00:00 12026 4
如果我想得到行,直到列集合的和等于13
DATE ETC Meeting
2013-02-01 00:00:00 85482 1
2013-02-01 00:00:00 47228 2
2013-02-02 00:00:00 12026 4
2013-02-03 00:00:00 78927 6
这是一个丑陋的方式:
SELECT *
FROM meetings m1
WHERE (SELECT SUM(m2.Meeting)
FROM meetings m2
WHERE m2.DATE < m1.DATE OR (m2.DATE = m1.DATE AND m2.ETC >= m1.ETC)) <= 7
排序首先基于日期,然后是降序的ETC,因为这似乎是我们必须继续的。请注意,如果这不是唯一的,您将得到错误的结果。如果您使用的是SQL Server,请使用。如果您没有说明使用的RDBMS,请使用。下面是一个t-sql脚本,您可以使用它来解决您的问题
DECLARE @numberToReach INT;
SET @numberToReach = 10; --you can change this
DECLARE @date DATETIME;
DECLARE @etc VARCHAR(20);
DECLARE @meeting INT;
DECLARE @temp_sum INT;
CREATE TABLE #tempTable
(
Dates DATETIME,
Etcs VARCHAR(20),
Meeting INT,
)
DECLARE tempcursor CURSOR FOR
SELECT *
FROM YourTABLENAME
OPEN tempcursor;
FETCH NEXT FROM tempcursor INTO @date, @etc, @meeting;
WHILE(@@FETCH_STATUS = 0)
BEGIN
SET @temp_sum = @temp_sum + @meeting;
IF @temp_sum < @numberToReach
BEGIN
INSERT INTO #tempTable
(
Dates,
Etcs,
Meeting
)
VALUES
(
@date,
@etc,
@meeting
)
FETCH NEXT FROM tempcursor INTO @date, @etc, @meeting;
END
END
SELECT * FROM #tempTable
CLOSE tempcursor
DEALLOCATE tempcursor
DROP TABLE #tempTable
在Oracle中,我认为可以使用求和分析函数。您可以参考这里:这里有一种在MySQL中工作的方法:
SELECT
O.Id,
O.Type,
O.MyAmountCol,
(SELECT
sum(MyAmountCol) FROM Table1
WHERE Id <= O.Id) 'RunningTotal'
FROM Table1 O
HAVING RunningTotal <= 7
它涉及计算运行总数并选择记录,而运行总数小于或等于给定的数字,在本例中为7
这里有一种不用存储过程的方法:
SET @msum := 0;
SELECT t1.*
FROM (
SELECT m.*,
(@msum := @msum + m.meetings) AS cumulative_meetings
FROM meetings m
ORDER BY m.date ASC
) t1
WHERE t1.cumulative_meetings <= 7;
由于未提供DBMS,以下是一个ANSI SQL解决方案,可用于各种DBMS:
select *
from (
select date_column,
etc,
sum(Meeting) over (order by date_column asc) run_sum
from meetings
) t
where run_sum <= 7
order by date_column asc;
我使用了列名称date\u列而不是date,因为date在SQL中是一个保留字,不应该用作列名以避免出现问题这一列的性能优于所有列
SET @runningTotal=0;
SELECT
O.Id,
O.Type,
O.MyAmountCol,
@runningTotal + O.MyAmountCol as 'RunningTotal',
@runningTotal := @runningTotal + O.MyAmountCol
FROM Table1 O
HAVING RunningTotal <=7;
看看这两个查询的执行计划 您使用的是哪种RDBMS、MS SQL Server、MySQL、PostgreSQL。。。?你试过什么?发布一些工作查询(不管结果是否不正确)是一个起点,也许您离解决方案不远。您似乎没有主键/无法建立考虑行的顺序这实际上是一个更好、更快的解决方案,用于处理大量数据。谢谢。如果每行的会议数多于X,则此查询将返回0行。id来自何处?注意,这可能发生在db服务器上的^2查询上,因为子选择在查询结束时增加,并且也没有提前停止,所有总和都将被计算。如果selects的范围很小,它的优点是作为单个查询,因此不需要存储过程等。Date不是保留字,并且在示例中日期不是唯一的provided@Strawberry:是日期是关键字,但不是保留日期。就连MySQL也这么认为:而且日期不一定非得是唯一的才行,谢谢。对于希望使用WHERE查询的用户,请改用AND