1

我有一个表(tbl_operations),其中 id 列值可能以逗号分隔。我想得到OpId每个月的计数。我正在尝试通过纯 sql 来完成此操作,但没有成功。

从这个角度看

操作 ID 操作日期
3 2022-01-03
5,3 2022-01-15
4 2022-01-27
5 2022-02-01
7 2022-02-09
3,2 2022-01-16

对此

操作 ID 数数
2 1 01
3 3 01
4 1 01
5 1 01
5 1 02
7 1 02

我被困在这里。有人可以告诉我如何使用 sql 来执行此操作吗?如果没有,也许使用 php 来显示结果?

SELECT tbl_operations.OpId,
    tbl_operations.OpDate ,
    COUNT(tbl_operations.OpId) AS `count`
FROM tbl_operations
WHERE MONTH(OpDate)=1
GROUP BY  tbl_operations.OpId
4

3 回答 3

1

这是一个简单的例子。第一部分只是创建一个数组数组来模拟您从数据库中获得的内容。

要点是这$counts是一个具有唯一 OpID 键的数组。这些数组的值是子数组,带有月份的键和找到它们的次数的值。

显示应该只是一个简单的循环,但是您可能想要对其进行排序。

$rows = [
['3',   '2022-01-03'],
['5,3', '2022-01-15'],
['4',   '2022-01-27'],
['5',   '2022-02-01'],
['7',   '2022-02-09'],
['3,2', '2022-01-16'],
];

$counts = [];
foreach($rows as $row){
    $ids = explode(',', $row[0]);
    $month = date('m', strtotime($row[1]));
    foreach($ids as $id){
        if(!array_key_exists($id, $counts)){
            $counts[$id] = [];
        }
        if(!array_key_exists($month, $counts[$id])){
            $counts[$id][$month] = 0;
        }
        
        $counts[$id][$month]++;
    }
}

此处演示:https ://3v4l.org/mVaBB

编辑

从@mickmackusa,您可以使用以下方法缩短内部循环isset

        if(!isset($counts[$id][$month])){
            $counts[$id][$month] = 0;
        }

查看他们的评论以获取演示链接

于 2022-02-16T12:37:12.153 回答
0

如果您要在 PHP 中查询数据,最好首先返回一个更好的结果以供使用:

SQL

SELECT GROUP_CONCAT(OpId), MONTH(OpDate)
FROM tbl_operations
GROUP BY MONTH(OpDate)

PHP

// Result from MySQL query
$rows = [
    ['3,5,3,4,3,2', 1],
    ['5,7', 2]
];

您可以像这样对这些分组结果进行计数:

$results = [];
foreach ($rows as $row) {
    $counts = array_count_values(explode(',', $row[0]));
    $results[$row[1]] = $counts;
}

结果

Array
(
    [1] => Array
        (
            [3] => 3
            [5] => 1
            [4] => 1
            [2] => 1
        )

    [2] => Array
        (
            [5] => 1
            [7] => 1
        )

)


您真正想要做的是标准化您的数据,然后您可以仅在 SQL 中轻松完成此操作。

于 2022-02-16T13:49:37.223 回答
0

如果您至少使用 MYSQL8 并且您不打算规范您的表设计,那么您实际上可以使用以下CTE查询来拆分、分组、格式化和排序您的结果集(无需 PHP 处理)。

这种方法对非规范化表进行递归调用,并逐步将最右边的 id 与逗号分隔的值隔离开来,并为各个 id 值生成新行。递归一直持续到没有逗号为止。

此解决方案建立在此处演示的基本技术之上。

SQL:(演示

WITH RECURSIVE norm AS (
    SELECT OpId,
           OpDate
    FROM tbl_operations
    UNION ALL
    SELECT REGEXP_REPLACE(OpId, '^[^,]*,', '') AS OpId,
           OpDate
    FROM norm
    WHERE OpId LIKE '%,%'
)
SELECT Id,
       Mo,
       COUNT(*) AS Cnt
FROM (
    SELECT REGEXP_REPLACE(norm.OpId, ',.*', '') AS Id,
           MONTH(norm.OpDate) AS Mo
    FROM norm
) formatted
GROUP BY formatted.Id, 
         formatted.Mo

结果集:

ID 计数
2 1 1
3 1 3
4 1 1
5 1 1
5 2 1
7 2 1

就是说,一旦您对表格进行规范化,这对于一项非常容易的任务来说,这是很多不必要的巫毒教 - 尽快对其进行规范化

于 2022-02-17T11:46:52.603 回答