【问题标题】:PHP PDO Fetch as multidimensional array with first column as key, and second & third as key-value pair [duplicate]PHP PDO Fetch作为多维数组,第一列作为键,第二和第三作为键值对[重复]
【发布时间】:2021-02-03 03:07:43
【问题描述】:

我有一个这样创建的 MySQL 数据库表

CREATE TABLE table1 (
    column1 varchar(50),
    column2 varchar(50),
    column3 int(3)
);

INSERT INTO table1
VALUES ("column1 value1", "column2 value1", 120),
("column1 value1", "column2 value1", 240),
("column1 value2", "column2 value1", 240),
("column1 value2", "column2 value2", 10);

在这张桌子上。我执行这个 SQL 查询:

SELECT column1, column2, SUM(column3) FROM table1 GROUP BY column1, column2

是否可以将结果提取到一个多维关联数组中,其中column1 作为“级别 1”键,column2 & column3 作为键值对?

想要的结果:

Array
(
    [column1 value] => Array
        (
            [column2 value] => column3 value
        )
)

我尝试使用 PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC 作为 fetch 样式参数,但结果是:

Array
(
    [column1 value] => Array
        (
            [column2 key] => column2 value
            [column3 key] => column3 value
        )
)

这就是我执行查询并获取结果的方式:

$stmt = $pdo->prepare("SELECT column1, column2, SUM(column3) FROM table GROUP BY column1, column2");
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC);

是否有一种 fetch 样式组合可以获得我想要的结果,还是我必须以编程方式执行此操作?

【问题讨论】:

标签: php mysql arrays multidimensional-array pdo


【解决方案1】:

遗憾的是,PDO::FETCH_GROUP 只会按获取的第一个列对结果进行分组,因此您将无法按 2 列进行分组。

但是您可以使用array_maparray_combinearray_column 将结果转换为您想要的结果

$stmt = $pdo->prepare("SELECT column1, column2, SUM(column3) as column3 FROM table1 GROUP BY column1, column2");
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);

$result = array_map(static function ($res) {
    return array_combine(
        array_column($res, 'column2'),
        array_column($res, 'column3')
    );
}, $result);

var_dump($result);

【讨论】:

  • 我用这个得到了一个空数组array(1) { ["column1"] => array(0) { } }
【解决方案2】:

基本上,您只能以编程方式执行此操作,但您可以使用fetchAll 调用中的函数来执行此操作;使用FETCH_GROUP按第一列进行分组,并使用函数从第二列和第三列返回适当的数组。

$result = $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_FUNC,
                          function ($col2, $col3) { 
                              return array($col2 => $col3); 
                          });

请注意,这会返回一个具有额外级别的数组:

Array
(
    [column1 value1] => Array
        (
            [0] => Array
                (
                    [column2 value1] => 360
                )
        )
    [column1 value2] => Array
        (
            [0] => Array
                (
                    [column2 value1] => 240
                )
            [1] => Array
                (
                    [column2 value2] => 10
                )
        )
)

您可以通过array_maparray_reduce 的组合来删除额外的级别:

$result = array_map(function ($arr) {
    return array_reduce($arr, function ($c, $a) {
        $c[key($a)] = reset($a);
        return $c;
    }, []);
}, $result);

输出:

Array
(
    [column1 value1] => Array
        (
            [column2 value1] => 360
        )
    [column1 value2] => Array
        (
            [column2 value1] => 240
            [column2 value2] => 10
        )
)

不过,循环遍历数组可能更简单:

$result = $stmt->fetchAll(PDO::FETCH_NUM);
$out = array();
foreach ($result as $array) {
    $out[$array[0]][$array[1]] = $array[2];
}

【讨论】:

  • @YourCommonSense 显然我应该阅读您的博客 - 我不知道 FETCH_UNIQUE 的功能,过去只看到它与 FETCH_GROUP 的组合。感谢您的编辑。直到。
  • 这种组合实际上没有意义,因为它会产生 FETCH_UNIQUE 值。但现在我不确定 FETCH_UNIQUE 是否真的是 OP 的意思
  • 如果你使用FETCH_GROUP而不使用FETCH_UNIQUE,你会在输出中得到一个额外的层(array($col1 => array(array($col2 => $col3)))),所以FETCH_UNIQUE是肯定需要的。
  • 就像我说的,使用 FETCH_GROUP 和 FETCH_UNIQUE 是没有意义的,实际上只是 FETCH_UNIQUE。是的,没有它你会得到一个额外的水平,但是你会失去一行数据。
  • 如何丢失一行数据?
【解决方案3】:

显然,PDO 获取模式中最难的部分是从 索引 中区分 分组。出于某种原因,与这些模式相关的每个问题都会让他们感到困惑。

从您查询的性质来看,我会说您需要分组。但是在您的多毛提取模式组合中,您使用的是 FETCH_UNIQUE,这会导致索引,而不是分组。

您提供了一些 MCVE 是一件好事 - 只有少数人在 PDO 标记下成功使用它,但您没有提供真正想要的结果,而只是一个草图,这是一件非常糟糕的事情。所以我只能猜测它一定是这样的

{
    "column1 value1": {
        "column2 value1": "360"
    },
    "column1 value2": {
        "column2 value1": "240",
        "column2 value2": "10"
    }
}

但您当前的方法是为您提供此数组短一行

我不知道任何可以为您提供所需结果的提取模式组合,但旧的良好手动提取始终可以

$sql = "SELECT column1, column2, SUM(column3) sum FROM table1 GROUP BY column1, column2";
$stmt = $pdo->query($sql);
$data = [];
foreach($stmt as $row) {
    $data[$row['column1']][$row['column2']] = $row['sum'];
}

最后,事实证明你的 MCVE 不是那么好。对你来说,这将是一个教训,始终创建一个可靠、有效且不矛盾的示例,并具有可以与实际结果进行比较的特定预期结果。

【讨论】:

  • 这也是我的结局......
猜你喜欢
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
相关资源
最近更新 更多