同事問到這樣一個需求:
~~~
現在要分頁列出所有用戶,并且要帶出每個用戶的最新一篇帖子的信息,如何實現。
~~~
我想起來以前寫過一個方法,用于分頁列出所有畫家,并且要帶出每個畫家的最新一幅作品信息。這連個需求其實是相同的。翻找了以前的代碼,總算找到了。
方法代碼(Laravel):
~~~
/**
* 獲取每個畫家最新一副作品
*
* @return \Illuminate\Http\JsonResponse
*/
public function artistsLatestProduct()
{
// 每個畫家(artists)有多幅作品(products)
// 先創建一個子查詢,用于獲取作品表中每個畫家最新一副作品的id列表(latest_product_ids)
$latestProductIdsQuery = Product::selectRaw('max(id) as latest_product_id')->groupBy('artist_id');
// latest_product_ids只是一組作品id,然后用products表連接臨時表latest_product_ids獲取latest_product_ids這些ids作品的全部信息
$latestProductQuery = Product::leftJoin(\DB::raw("({$latestProductIdsQuery->toSql()}) as latest_product_ids"), 'latest_product_ids.latest_product_id', '=', 'products.id')
->mergeBindings($latestProductIdsQuery->getQuery())
->select(['products.*'])
->whereNotNull('latest_product_id');
// 現在獲取到了想要的作品列表了,放在臨時表latest_products中,并和artists表連接,獲取每個畫家的信息和該畫家對應的最新作品的信息
$columns = [
'artists.id',
'artists.name as artist_name',
'latest_products.id as latest_product_id',
'latest_products.title as latest_product_title'
];
$perPage = 10;
$artistsWithLatestProduct = Artist::leftJoin(\DB::raw("({$latestProductQuery->toSql()}) as latest_products"), 'latest_products.artist_id', '=', 'artists.id')
->mergeBindings($latestProductQuery->getQuery())
->paginate($perPage, $columns);
return $this->responseData($artistsWithLatestProduct);
}
~~~
翻譯成MySQL查詢語句如下:
~~~
SELECT
artists.id,
artists.`name` AS artist_name,
latest_products.id AS latest_product_id,
latest_products.title AS latest_product_title
FROM
artists
LEFT JOIN (
SELECT
products.*
FROM
products
LEFT JOIN (
SELECT
MAX(id) AS latest_product_id
FROM
`products`
GROUP BY
artist_id
) AS latest_product_ids ON latest_product_ids.latest_product_id = products.id
WHERE
latest_product_id IS NOT NULL
) AS latest_products ON latest_products.artist_id = artists.id;
~~~
查詢結果如下:
~~~
{
code: 200,
message: "操作成功",
data: {
current_page: 1,
data: [
{
id: 1,
artist_name: "張三",
latest_product_id: 5,
latest_product_title: "回憶"
},
{
id: 2,
artist_name: "李四",
latest_product_id: 8,
latest_product_title: "開市"
}
],
from: 1,
last_page: 1,
next_page_url: null,
path: "http://wechat.zhouye.app/artists_with_latest_product",
per_page: 10,
prev_page_url: null,
to: 2,
total: 2
}
}
~~~