【发布时间】:2019-09-04 10:31:28
【问题描述】:
我一直在尝试使用SUM() 来汇总我数据库中的一些数值,但它似乎返回了意外的值。这是生成 SQL 的 PHP 端:
public function calcField(string $field, array $weeks)
{
$stmt = $this->conn->prepare('SELECT SUM(`'. $field .'`) AS r FROM `ws` WHERE `week` IN(?);');
$stmt->execute([implode(',', $weeks)]);
return $stmt->fetch(\PDO::FETCH_ASSOC)['r'];
}
让我们为大家提供一些示例数据:
$field = 'revenue';
$weeks = [14,15,16,17,18,19,20,21,22,23,24,25,26];
这会返回这个值:
4707.92
在没有看到数据的情况下,这似乎已经奏效,但以下是那几周的行:
+----+------+------+---------+-------+---------+---------+------+----------+
| id | week | year | revenue | sales | gpm_ave | uploads | pool | sold_ave |
+----+------+------+---------+-------+---------+---------+------+----------+
| 2 | 14 | 2019 | 4707.92 | 292 | 13 | 0 | 1479 | 20 |
| 3 | 15 | 2019 | 4373.32 | 304 | 13 | 0 | 1578 | 19 |
| 4 | 16 | 2019 | 4513.10 | 275 | 14 | 0 | 1460 | 19 |
| 5 | 17 | 2019 | 4944.80 | 336 | 14 | 0 | 1642 | 20 |
| 6 | 18 | 2019 | 4343.87 | 339 | 13 | 0 | 1652 | 21 |
| 7 | 19 | 2019 | 3918.59 | 356 | 14 | 0 | 1419 | 25 |
| 8 | 20 | 2019 | 4091.20 | 247 | 19 | 0 | 1602 | 15 |
| 9 | 21 | 2019 | 4177.22 | 242 | 12 | 0 | 1588 | 15 |
| 10 | 22 | 2019 | 3447.88 | 227 | 18 | 0 | 1585 | 14 |
| 11 | 23 | 2019 | 3334.18 | 216 | 15 | 0 | 1675 | 13 |
| 12 | 24 | 2019 | 4736.15 | 281 | 13 | 0 | 1388 | 20 |
| 13 | 25 | 2019 | 4863.84 | 252 | 12 | 0 | 1465 | 17 |
| 14 | 26 | 2019 | 4465.95 | 281 | 21 | 0 | 1704 | 16 |
+----+------+------+---------+-------+---------+---------+------+----------+
如您所见,总数应该远远大于4707.92 - 我注意到第一行收入 = 4707.92。
如果我将它添加到函数中,事情会变得很奇怪:
echo 'SELECT SUM(`'. $field .'`) AS r FROM `ws` WHERE `week` IN('. implode(',', $weeks) .');';
哪些输出:
SELECT SUM(revenue) AS r FROM ws WHERE week IN(14,15,16,17,18,19,20,21,22,23,24,25,26);
将其复制并粘贴到 MySQL CLI 中返回:
MariaDB [nmn]> SELECT SUM(revenue) AS r FROM ws WHERE week IN(14,15,16,17,18,19,20,21,22,23,24,25,26);
+----------+
| r |
+----------+
| 55918.02 |
+----------+
1 row in set (0.00 sec)
哪个,看起来更准确。但是,同样的 SQL 语句会返回第一行的值,而不是对那几周的列求和。
此函数由 AJAX 脚本触发:
$d = new Page\Snapshot\D();
# at the minute only outputting dump of values to see what happens
echo '<pre>'. print_r(
$d->getQuarterlySnapshot(new Page\Snapshot\S(), new App\Core\Date(), $_POST['quarter'], '2019'),
1
). '</pre>';
函数$d->getQuarterlySnapshot函数:
public function getQuarterlySnapshot(S $s, Date $date, int $q, string $year)
{
switch($q)
{
case 1:
$start = $year. '-01-01 00:00:00';
$end = $year. '-03-31 23:59:59';
break;
case 2:
$start = $year. '-04-01 00:00:00';
$end = $year. '-06-30 23:59:59';
break;
case 3:
$start = $year. '-07-01 00:00:00';
$end = $year. '-09-30 23:59:59';
break;
case 4:
$start = $year. '-10-01 00:00:00';
$end = $year. '-12-31 23:59:59';
break;
}
$weeks = $date->getWeeksInRange('2019', 'W', $start, $end);
foreach ($weeks as $key => $week){$weeks[$key] = $week[0];}
return [
'rev' => $s->calcField('revenue', $weeks),
'sales' => $s->calcField('sales', $weeks),
'gpm_ave' => $s->calcField('gpm_ave', $weeks),
'ul' => $s->calcField('uploads', $weeks),
'pool' => $s->calcField('pool', $weeks),
'sold_ave' => $s->calcField('sold_ave', $weeks)
];
}
所以我不会在任何地方覆盖该值(至少我可以看到)。如何将SUM() 与IN() 条件结合使用?
【问题讨论】:
-
您可能的意思是使用
where id IN (...而不是where week in (..,因为您最后显示的数据是从 id = 1 到 13 -
@MadhurBhaiya 啊,不,我的意思是一周 - 但实际上并没有在一秒钟内检查周值 xD,让我快速测试另一个......更多的人口范围并回复你 xD
-
将货币值存储为浮点数不是一个好主意
-
更改表格以添加一个十进制类型的新列
revenue_decimal.. 运行UPDATE SET revenue_decimal = revenue ....并检查...之间的数据... 当数据正确时删除浮点类型并重命名十进制类型.. 或者创建一个新表,这也是可能的并运行INSERT INTO new_table SELECT * FROM old_table.. 无论如何不要对生活数据进行数据类型转换,在这种情况下最有可能不会发生任何坏事,但最好是安全然后抱歉..