SQL результатов в массив без дублирования идентификатора и post_title в одном массиве - PullRequest
2 голосов
/ 25 мая 2020

Я работаю над полученными данными из базы данных. Мне нужны эти данные в массиве, но ID и post_title возвращают более одного результата.

wp_posts
+----+------------+
| ID | post_title |
| 1  | radio      |
| 2  | television |
+----+------------+

wp_postmeta
+---------+---------+----------+------------+ 
| meta_id | post_id | meta_key | meta_value |
|    1    |    1    | price    | 12.50      |
|    2    |    1    | _sku     | 5876gh7    |
|    3    |    1    | thumb_id | 56         |
|    4    |    2    | price    | 342.50     |
|    5    |    2    | _sku     | tv784      |
|    6    |    2    | thumb_id | 78         |
+---------+---------+----------+------------+ 

$query = "
    SELECT p.ID, p.post_title, m.meta_id, m.meta_key, m.meta_value
    FROM wp_posts p
    LEFT JOIN wp_postmeta m ON (m.post_id = p.ID)
    WHERE EXISTS (SELECT 1 FROM wp_posts WHERE post_title LIKE '%rad%' AND ID = p.ID)
    OR EXISTS (SELECT 1 FROM wp_postmeta WHERE meta_key = '_sku' AND meta_value LIKE '%rad%' AND post_id = p.ID)
    ORDER BY p.ID, m.meta_id
";


$result     = mysqli_query($connection, $query);

while($row = $result->fetch_object() ){
        $sendback[] = $row;
}

print_r($sendback);

Это результат, который я увижу, если напечатаю это. Вы можете видеть, что ID и post_title отображаются в каждом результате.

array(
    [0] => stdClass Object ( 
        [ID]            => 1 
        [post_title]    => Radio  
        [meta_key]      => price 
        [meta_value]    => 12.50 
    ) 
    [1] => stdClass Object ( 
        [ID]            => 1 
        [post_title]    => Radio  
        [meta_key]      => _sku 
        [meta_value]    => 5876gh7
    )
    [2] => stdClass Object ( 
        [ID]            => 1 
        [post_title]    => Radio  
        [meta_key]      => thumb_id 
        [meta_value]    => 56
    )
)

Какой метод я могу использовать для получения идентификатора и post_title один раз, как это

array(
        'id'            => '1',
        'post_title'    => 'radio',
        'price'         => '12.50',
        'sku'           => '5876gh7',
        'thumb_id'      => '56'
    )

Ответы [ 2 ]

0 голосов
/ 26 мая 2020

Если вы заранее знаете список мета-ключей, которые хотите вернуть, вы можете использовать условную агрегацию, чтобы развернуть свой набор данных и получить ожидаемые результаты:

SELECT 
    p.ID, 
    p.post_title, 
    MAX(CASE WHEN m.meta_key = 'price'    THEN m.meta_value END) price,
    MAX(CASE WHEN m.meta_key = '_sku'     THEN m.meta_value END) sku,
    MAX(CASE WHEN m.meta_key = 'thumb_id' THEN m.meta_value END) thumb_id
FROM wp_posts p
LEFT JOIN wp_postmeta m ON m.post_id = p.ID
WHERE 
    EXISTS (SELECT 1 FROM wp_posts WHERE post_title LIKE '%rad%' AND ID = p.ID)
    OR EXISTS (SELECT 1 FROM wp_postmeta WHERE meta_key = '_sku' AND meta_value LIKE '%rad%' AND post_id = p.ID)
GROUP BY p.ID, p.post_title
ORDER BY p.ID

Я также подозреваю, что подзапросы в предложении WHERE можно упростить:

SELECT 
    p.ID, 
    p.post_title, 
    MAX(CASE WHEN m.meta_key = 'price'    THEN m.meta_value END) price,
    MAX(CASE WHEN m.meta_key = '_sku'     THEN m.meta_value END) sku,
    MAX(CASE WHEN m.meta_key = 'thumb_id' THEN m.meta_value END) thumb_id
FROM wp_posts p
LEFT JOIN wp_postmeta m ON m.post_id = p.ID
GROUP BY p.ID, p.post_title
HAVING 
    p. post_title LIKE '%rad%'
    OR MAX(CASE WHEN m.meta_key = '_sku' AND m.meta_value LIKE '%rad%' THEN 1 ELSE 0 END) = 1
ORDER BY p.ID
0 голосов
/ 26 мая 2020

Невозможно решить эту проблему напрямую, используя только SQL, вам нужно будет обработать эти записи. Причина в том, что wp_postmeta имеет много записей для одной записи wp_posts. Итак, что вы можете сделать:

$SQL = <<<SQL
  SELECT *
  FROM wp_posts
SQL;

$posts = $dbh->query($SQL)->fetchAll();

У вас будут все ваши сообщения

foreach($posts as $post) {
  $prodArr[]['id'] = $post['id'];
  $prodArr[count($prodArr) - 1]['post_title'] = $post['post_title'];
  $SQL = <<<SQL
    SELECT *
    FROM wp_postmeta
    WHERE post_id = {$post['id']}
SQL;
  $metas = $dbh->query($SQL)->fetchAll();
  foreach($metas as $meta) {
    if ($meta['meta_key'] == 'price')
      $prodArr[count($prodArr) - 1]['price'] = $meta['meta_key'];
    else if ($meta['meta_key'] == '_sku')
      $prodArr[count($prodArr) - 1]['sku'] = $meta['meta_key'];
    else if ($meta['meta_key'] == 'thumb_id')
      $prodArr[count($prodArr) - 1]]['thumb_id'] = $meta['meta_key'];
  }
}

Таким образом, $ prodArr будет иметь всю информацию, которая вам нужна для всех продуктов, а затем вы можно повторить. Код может содержать ошибки, я не тестировал.

...