这可能有点令人困惑,但请耐心等待。事情就是这样:
我有一个包含~1000条记录的数据库,如下表所示:
+------+----------+----------+
| id | date | amount |
+------+----------+----------+
| 0001 | 14/01/15 | 100 |
+------+----------+----------+
| 0002 | 14/02/04 | 358 |
+------+----------+----------+
| 0003 | 14/05/08 | 1125 |
+------+----------+----------+
我想做的是:
检索从2014年开始直到昨天的所有记录:
WHERE `date` > '14-01-01' AND `date` < CURDATE()
但是也可以得到amount
到当前日期的总和,这是:
WHERE `date` < CURDATE()
我已经通过根据第二个条件选择所有记录,获得总和,然后排除那些与第一个条件不匹配的记录来完成此工作。像这样:
SELECT `id`, `date`, `amount` FROM `table`
WHERE `date` < CURDATE()
然后:
$rows = fetchAll($PDOStatement);
foreach($rows as $row) {
$sum += $row->amount;
if (
strtotime($row->date) > strtotime('14-01-01') &&
strtotime($row->date) < strtotime(date('Y-m-d'))
) {
$valid_rows[] = $row;
}
}
unset $rows;
有效的方法是在单个查询中实现此目的吗? 事务比在PHP中整理记录更有效吗?这必须符合SQL标准(我将在MySQL和SQLite上执行此操作)。
更新
如果结果最终是这样的话无关紧要:
+------+----------+----------+-----+
| id | date | amount | sum |
+------+----------+----------+-----+
| 0001 | 14/01/15 | 100 | 458 |
+------+----------+----------+-----+
| 0002 | 14/02/04 | 358 | 458 |
+------+----------+----------+-----+
| 0003 | 14/05/08 | 1125 | 458 |
+------+----------+----------+-----+
最糟糕的情况是,结果集合最终与给出总和的集合相同(在这种情况下,附加总和将是无关的并且会导致开销),但对于任何其他常规< / em>案例带宽保存将是巨大的。
答案 0 :(得分:1)
编辑:
您可以使用LEFT OUTER JOIN获取SUM。
SELECT t1.`id`, t1.`date`, t2.sum_amount
FROM
`table` t1
LEFT OUTER JOIN
(
SELECT SUM(`amount`) sum_amount
FROM `table`
WHERE `date` < CURDATE()
) t2
ON 1 = 1
WHERE t1.`date` > STR_TO_DATE('01,1,2014','%d,%m,%Y') AND t1.`date` < CURDATE();
答案 1 :(得分:1)
您可以使用总和创建特殊记录,并在第一个查询结束时添加
SELECT * FROM `table` WHERE `date` > '14-01-01' AND `date` < CURDATE()
UNION
SELECT 9999, CURDATE(), SUM(`amount`) FROM `table` WHERE `date` < CURDATE()
然后你将获得所有你想要的记录和id为9999的记录或者你的总和
答案 2 :(得分:1)
这可以通过相关子查询来实现,如下所示:
SELECT *, (SELECT SUM(amount) FROM t WHERE t.date < t1.date) AS PrevAmount
FROM t AS t1
WHERE `date` > '14-01-01' AND `date` < CURDATE()
但是,如果记录数量很大,则效率非常低。
答案 3 :(得分:1)
这是hackish,但是:
> select * from foo;
+------+------+
| id | val |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
+------+------+
5 rows in set (0.02 sec)
> select * from foo
left join (
select sum(val)
from foo
where id < 3
) AS bar ON 1=1
where id < 4;
+------+------+----------+
| id | val | sum(val) |
+------+------+----------+
| 1 | 1 | 3 |
| 2 | 2 | 3 |
| 3 | 3 | 3 |
+------+------+----------+
基本上,在连接的子查询中进行求和。这会将总和结果附加到外表结果中的每一行。你会浪费一些带宽来发送每一行重复的值,但它确实可以让你得到一个单一的&#34;查询。
答案 4 :(得分:1)
这将做你想做的事情......优化子查询是真正的挑战:
SELECT id,date,amount,(SELECT SUM(amount) FROM table) AS total_amount
FROM table
WHERE date BETWEEN '14-01-01' AND DATE_ADD(CURDATE(), INTERVAL -1 DAY)