Pertanyaan MySQL LEFT JOIN, GROUP BY dan ORDER BY tidak berfungsi sesuai kebutuhan


Saya punya meja

'products' => ('product_id', 'name', 'description') 

dan sebuah meja

'product_price' => ('product_price_id', 'product_id', 'price', 'date_updated')

Saya ingin melakukan permintaan seperti itu

SELECT `p`.*, `pp`.`price` 
FROM `products` `p` 
LEFT JOIN `product_price` `pp` ON `pp`.`product_id` = `p`.`product_id`
GROUP BY `p`.`product_id` 
ORDER BY `pp`.`date_updated` DESC

Karena Anda mungkin bisa menebak perubahan harga sering dan saya harus mengeluarkan yang terbaru. Masalahnya adalah saya tidak dapat mengetahui cara memesan tabel LEFT JOINed. Saya mencoba menggunakan beberapa fungsi GROUP BY seperti MAX () tetapi itu hanya akan menarik keluar kolom bukan baris.

Terima kasih.


9
2018-01-02 20:56


asal


Jawaban:


Tampaknya itu benar mustahil untuk menggunakan ORDER BY pada GRUP OLEH ringkasan. Logika fundamental saya cacat. Saya harus menjalankan subkueri berikut.

SELECT `p`.*, `pp`.`price` FROM `products` `p` 
LEFT JOIN (
    SELECT `price` FROM `product_price` ORDER BY `date_updated` DESC
) `pp` 
ON `p`.`product_id` = `pp`.`product_id`
GROUP BY `p`.`product_id`;

Ini akan menghasilkan kinerja, tetapi karena ini adalah subkueri yang sama untuk setiap baris, itu seharusnya tidak terlalu buruk.


16
2018-01-02 23:50



Anda perlu mengatur alias dengan benar saya pikir dan juga mengatur apa yang Anda bergabung di:

SELECT p.*, pp.price 
FROM products AS p 
LEFT JOIN product_price AS pp
ON pp.product_id = p.product_id 
GROUP BY p.product_id 
ORDER BY pp.date_updated DESC

1
2018-01-02 21:17



Ini akan memberi Anda harga terakhir yang diperbarui:

select
  p.*, pp.price
from
  products p,
  -- left join this if products may not have an entry in prodcuts_price
  -- and you would like to see a null price with the product
  join 
  (
      select 
        product_price_id, 
        max(date_updated) 
      from products_price
      group by product_price_id
   ) as pp_max
    on p.product_id = pp.product_id
  join products_price pp on 
    pp_max.prodcuts_price_id = pp.products_price_id

-1
2018-01-02 21:18



Mysqlism:

SELECT p.*, MAX(pp.date_updated), pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id
GROUP BY p.product_id 

Akan bekerja pada beberapa RDBMS:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE (p.product_id, pp.date_updated) 

   in (select product_id, max(date_updated) 
       from product_price 
       group by product_id)

Akan bekerja pada sebagian besar RDBMS:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id

WHERE EXISTS
(
    select null -- inspired by Linq-to-SQL style :-)
    from product_price 

    WHERE product_id = p.product_id 

    group by product_id

    HAVING max(date_updated) = pp.date_updated
)

Akan bekerja di semua RDBMS:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id

LEFT JOIN 
(
    select product_id, max(date_updated) as recent 
    from product_price 
    group by product_id
) AS latest 
ON latest.product_id = p.product_id AND latest.recent = pp.date_updated

Dan jika nate cMaksud kode adalah hanya mendapatkan satu baris dari product_price, tidak perlu table-diturunkan (yaitu. join (select product_price_id, max(date_updated) from products_price) as pp_max), ia mungkin juga hanya menyederhanakan (yaitu tidak perlu menggunakan product_price_id pengganti kunci primer) itu seperti yang berikut:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE pp.date_updated = (select max(date_updated) from product_price)

-2
2018-01-03 03:15