簡體   English   中英

MySQL查詢從另一個表中檢索相關數據

[英]MySQL query to retrieve related data from another table

我對 SQL 查詢不太熟悉(大多數時候我使用框架中的查詢構建器,如 CodeIgniter 和 Laravel)。 現在,我需要從具有兩個表的關系數據庫中檢索數據:一個用於實體條目,另一個用於實體的補充數據。 例如,見下文:

tbl_posts

ID 姓名 蛞蝓
1 Lorem ipsum lorem-ipsum
2 測試帖 測試站
3 你好世界 你好世界

tbl_posts_meta

ID post_id 鑰匙 價值
1 1 約翰
2 1 能源部
3 1 評分 5
4 2 父母 1
5 2 評分 3
6 3 評分 4

在這個例子中,我需要以這種格式檢索一個對象數組:

[
  {
    id: 1,
    name: "Lorem ipsum",
    slug: "lorem-ipsum",
    data: {
      first_name: "John",
      last_name: "Doe",
      rating: 5,
    }
  },
  {
    id: 2,
    name: "Testing post",
    slug: "testing-post",
    data: {
      parent: 1,
      rating: 3,
    }
  },
  {
    id: 3,
    name: "Hello World",
    slug: "hello-world",
    data: {
      rating: 4,
    }
  },
]

我已經嘗試使用子查詢來處理這個問題,但我正在恢復Cardinality violation: 1241 Operand should contain 1 column(s)錯誤。 我的查詢如下所示:

SELECT *,(SELECT * FROM tbl_posts_meta WHERE "post_id" = "tbl_posts"."id") as data FROM tbl_posts;

我已經嘗試過使用 JOIN,但結果看起來與預期相差甚遠(結果中有一個“鍵”屬性和一個“值”屬性,包含 tbl_posts_meta 中最后找到的條目)。

SELECT * FROM tbl_posts INNER JOIN tbl_posts_meta ON tbl_posts_meta.post_id = tbl_posts.id;

有沒有辦法通過一個查詢來檢索所需的結果? 我不想通過 applogic 執行此操作(例如首先從 tbl_posts 檢索數據並在“data”屬性上附加另一個查詢,該查詢返回來自 tbl_posts_meta 的所有數據),因為這種方式可能會導致數據庫過載。

謝謝!

該代碼未在評論中正確顯示,因此您可以在這里檢查,抱歉,我無法為理論辯論做出更多貢獻:

select 
tp.id,
tp.name,
tp.slug,
(select group_concat(`key`, "=",value separator ';' ) from tbl_posts_meta where post_id= tp.id )as datas
from tbl_posts tp

您可以按照以下簡單步驟獲取所需的 json:

  • 連接兩個表以獲得集中的數據
  • 通過使用GROUP_CONCAT聚合函數聚合您感興趣的列( tbl_posts.idtbl_posts.nametbl_posts.slug )來生成類似tbl_posts_meta的 JSON 字符串。 由於您的鍵可以是整數或字符串,因此您需要使用CAST(<col> AS UNSIGNED)進行快速檢查,如果字符串不是數字,它將返回 0。
  • 使用JSON_OBJECT函數將每一行轉換為 JSON
  • 使用JSON_ARRAYAGG函數將所有 json 合並為一個 json。
WITH cte AS(
    SELECT p.id,
           p.name, 
           p.slug,
           CONCAT('{',
                  GROUP_CONCAT(
                      CONCAT('"', 
                             m.key_, 
                             '": ', 
                             IF(CAST(m.value_ AS UNSIGNED)=0, 
                                CONCAT('"', m.value_, '"'),
                                CAST(m.value_ AS UNSIGNED))  ) 
                      ORDER BY m.id                             ),
                  '}') AS data_
    FROM       tbl_posts      p
    INNER JOIN tbl_posts_meta m
            ON p.id = m.post_id
    GROUP BY p.id,
             p.name, 
             p.slug
)
SELECT JSON_ARRAYAGG(
           JSON_OBJECT("id",   id, 
                       "name", name, 
                       "slug", slug, 
                       "data", CAST(data_ AS JSON))) 
FROM cte

此處查看演示。

經過一些研究、測試和閱讀您在此處發布的查詢,我終於達到了我需要的結果。 最終查詢的結構如下:

SELECT *, (
  SELECT JSON_ARRAYAGG(
    JSON_OBJECT(
      key, value
    )
  ) FROM tbl_posts_meta WHERE post_id = post.id
) AS data
FROM tbl_posts;

將其轉換為 Laravel 的 Eloquent 查詢構建器,並使用 PHP 的序列化/反序列化函數,最終結果如下所示:

$posts = Post::query()
          ->select("*")
          ->selectRaw('(SELECT JSON_ARRAYAGG(JSON_OBJECT(key, value)) FROM tbl_posts_meta WHERE post_id = posts.id) as data');

return $posts->get()->map(function($post){
  $meta = [];
  foreach($post->data as $dataItem){
    foreach($dataItem as $key => $value){
      $meta[$key] = unserialize($value);
    }
  }
  $post->data = $meta;
  return $post;
});

感謝您的支持和關注! :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM