简体   繁体   中英

How to fetch a row which is related to multiple rows in another table?

I have some tables:

ws_shop_product

CREATE TABLE `ws_shop_product` (
     `product_id` int(10) unsigned NOT NULL AUTO_INCREMENT
     `product_title` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
 PRIMARY KEY (`product_id`)
) ENGINE=MyISAM AUTO_INCREMENT=14499 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci

ws_system_admin

CREATE TABLE `ws_system_admin` (
     `admin_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
     `admin_username` varchar(255) NOT NULL,
     `admin_password` char(40) NOT NULL,
 PRIMARY KEY (`admin_id`)
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

ws_shop_product-updated

CREATE TABLE `ws_shop_product-updated` (
     `updated_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
     `updated_product` int(10) unsigned DEFAULT NULL,
     `updated_admin` int(10) unsigned DEFAULT NULL,
     `updated_date` datetime DEFAULT NULL,
 PRIMARY KEY (`updated_id`),
 KEY `updated_product` (`updated_product`),
 KEY `updated_admin` (`updated_admin`)
) ENGINE=MyISAM AUTO_INCREMENT=42384 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci

Whenever a product has been changed in the CMS, one row will insert into the ws_shop_product-updated which keep the admin ID, product ID and date .

Some data:

product_id    product_title
----------    -------------
         1    iPhone 5     


updated_product    updated_admin    updated_date
---------------    -------------    ------------
              1              301    2013-04-13 00:00:00
              1              302    2013-04-15 00:00:00
              1              303    2013-04-16 00:00:00


Now my question is: How can I fetch products with latest update information?

product_id    product_title    latest_admin_id    latest_date
----------    -------------    ---------------    -----------
         1    iPhone 5         303                2013-04-16 00:00:00

You could use a query like this:

SELECT
  p.product_id,
  p.product_title,
  u.updated_admin latest_admin_id,
  u.updated_date latest_date
FROM
  `ws_shop_product-updated` u INNER JOIN ws_shop_product p
  ON u.updated_product = p.product_id
WHERE
  (u.updated_product, u.updated_date) IN
  (SELECT   updated_product, MAX(updated_date)
   FROM     `ws_shop_product-updated`
   GROUP BY product_id)

Please see fiddle here .

The subquery will return the maximum updated_date for each product, the outer query will return all columns of all rows that have the maximum updated_date for every product.

Because you are using mysql, you can use mysql's special (and non-portable) group by functionality to produce this fairly simple query:

SELECT * FROM (
  SELECT p.product_id, p.product_title,
    u.updated_admin latest_admin_id, u.updated_date latest_date
  FROM ws_shop_product p
  LEFT JOIN `ws_shop_product-updated` u ON u.updated_product = p.product_id
  ORDER BY u.updated_date DESC) x
GROUP BY 1

This query will return all products, even if they don't have a row in the "updated" table - returning null values for the "latest" columns when there's no such row.

The reason this works is that (for mysql only) when not all non-aggregated columns are named in the group by, mysql returns the first row found for each unique combination of values of columns named in the group by clause. By ordering the data in the subquery latest-first, the first row found for each product_id will be the latest.

You can try this :

WITH    CTE ( PRODUCTID, PRODUCT_TITLE )
                  AS ( SELECT   *
                       FROM     dbo.ws_shop_product
                     ),
                CTE2 ( updated_id, updated_product, updated_admin, updated_date, ROW )
                  AS ( SELECT   * ,
                                ROW = ROW_NUMBER() OVER ( PARTITION BY UPDATED_PRODUCT ORDER BY UPDATED_DATE DESC )
                       FROM     dbo.ws_shop_productupdated
                     )
            SELECT  A.* ,
                    B.UPDATED_ADMIN ,
                    UPDATED_DATE
            FROM    CTE A
                    JOIN CTE2 B ON A.PRODUCTID = B.UPDATED_PRODUCT
            WHERE   ROW = 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM