I have some tables:
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
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;
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.