Запрос объединения PHP MYSQL

#php #mysql #wordpress #woocommerce

#php #mysql #wordpress #woocommerce

Вопрос:

Я новичок в запросах mysql, и у меня возникли проблемы с получением нужной структуры данных. Я надеюсь, что один из вас, ребята, сможет помочь.

У меня есть следующий запрос:

 SELECT *
FROM wp_postmeta
WHERE post_id IN (SELECT id from wp_posts WHERE post_type = 'product')
  

Который просто захватывает все данные из таблицы 2, которые имеют тот же идентификатор, что и продукт в таблице 1. Проблема в том, что результаты возвращаются как:

 {meta_id: "37230", post_id: "2549", meta_key: "total_sales", meta_value: "0"}
{meta_id: "37231", post_id: "2549", meta_key: "_virtual", meta_value: "no"}
{meta_id: "37232", post_id: "2549", meta_key: "_tax_status", meta_value: "taxable"}
{meta_id: "37233", post_id: "2549", meta_key: "_visibility", meta_value: "visible"}
{meta_id: "37234", post_id: "2549", meta_key: "_featured", meta_value: "no"}
{meta_id: "37235", post_id: "2549", meta_key: "_weight", meta_value: "0.50"}
{meta_id: "37236", post_id: "2549", meta_key: "_sku", meta_value: "HCS-DGMP"}
{meta_id: "37237", post_id: "2549", meta_key: "_product_attributes", meta_value: "a:0:{}"}
{meta_id: "37238", post_id: "2549", meta_key: "_regular_price", meta_value: "18.99"}
{meta_id: "37239", post_id: "2549", meta_key: "_sale_price", meta_value: ""}
  

Как вы можете видеть, все они имеют одинаковый идентификатор записи, но возвращаются в виде отдельных объектов. Как я могу изменить свой запрос выше, чтобы все это возвращалось в одном объекте? Я также удалю meta_id , поскольку это бесполезно.

Комментарии:

1. Выполните цикл по всем массивам и создайте новый массив, ключами которого являются meta_key , а значениями являются meta_value

2. @Barmar Хм, это правда. Нет ли способа настроить запрос для этого? Или ваше предложение было бы более эффективным?

3. Что вы имеете в виду под «отдельными объектами»? Результирующие наборы состоят из строк , а не из объектов .

4. @GordonLinoff в зависимости от настроек или режима выборки PHP может возвращать строки как объекты со столбцами в качестве атрибутов объекта. Однако — Эта часть (получение результата в PHP) отсутствует в этом ответе.

Ответ №1:

Начиная с MySQL 5.7.22, вы можете использовать JSON_OBJECTAGG(key, value) :

 SELECT post_id, JSON_OBJECTAGG(meta_key, meta_value) AS meta_data
FROM wp_postmeta
WHERE post_id IN (SELECT id from wp_posts WHERE post_type = 'product')
GROUP by post_id
  

Это вернет meta_data как JSON_OBJECT с key: value парами:

 post_id | meta_data
   2549 | {"_sku": "HCS-DGMP", "_weight": "0.50", "_virtual": "no", "_featured": "no", "_sale_price": null, "_tax_status": "taxable", "_visibility": "visible", "total_sales": "0", "_regular_price": "18.99", "_product_attributes": "a:0:{}"}
  

ДЕМОНСТРАЦИЯ

Если ваш сервер не поддерживает JSON_OBJECTAGG() , я бы использовал PHP-решение:

 $postIds = array_unique(array_column($dbResult, 'post_id'));

$posts = [];
foreach ($postIds as $id) {
    $posts[$id] = (object)['id' => $id];
}

foreach ($dbResult as $row) {
    $posts[$row->post_id]->{$row->meta_key} = $row->meta_value;
}

echo json_encode(array_values($posts), JSON_PRETTY_PRINT);
  

Результат:

 [
    {
        "id": "2549",
        "total_sales": "0",
        "_virtual": "no",
        "_tax_status": "taxable",
        "_visibility": "visible",
        "_featured": "no",
        "_weight": "0.50",
        "_sku": "HCS-DGMP",
        "_product_attributes": "a:0:{}",
        "_regular_price": "18.99",
        "_sale_price": ""
    }
]
  

ДЕМОНСТРАЦИЯ

Пока вы не обрабатываете тысячи строк, я бы не беспокоился о производительности.

Комментарии:

1. О, чувак, это довольно аккуратно, ненавижу застрять на 5.6, который JSON_OBJECTAGG кажется полезным

2. @MiroslavGlamuzina С 5.6 вы можете эмулировать это с помощью GROUP_CONCAT . Но значения могут не содержать двойных кавычек или нулей. Я бы написал PHP-решение, которое не было бы таким ужасно сложным.

3. Да, я знаю, но это просто выглядит намного лучше. Да, это было бы не так уж плохо, но этот IMO был бы чище. Просто нужны json_ecode , array_combine и два array_columns , но тогда вам пришлось бы извлекать все эти дополнительные данные D:

4. @MiroslavGlamuzina Дополнительные данные — это всего лишь один INT (post_id) на пару ключ-значение — так что не так уж и много. Я мог бы даже предпочесть PHP-решение с более новыми версиями MySQL, потому что оно более гибкое.