简体   繁体   中英

How to get other columns from a row when using an aggregate function?

I'm embarrassed to say that I've been trying to accomplish this for hours without success. I've read dozens of similar questions on StackOverflow and tried countless different things, but I simply do not have a good enough grasp of SQL to achieve what I'm trying to accomplish.

I have two tables, products and product_prices . For simplicity, suppose they look like the following:

products:
id   


product_prices:
id | p_id | price | date_added

What I need to do is get the most recently added price, along with the date that price was added. So, in other words, for each product, I need to get the most recent price and date_added (along with the product id, p_id , of course).

If I only needed to get the most recent date and price for one product whose ID is known, then I can do it with this:

SELECT price, date_added 
FROM product_prices
WHERE p_id = 1
ORDER BY date_added DESC LIMIT 1

However, this type of query will not work when I need to get the most recent date and price for all of the products.

I believe the solution is to use the MAX() aggregate function in conjunction with GROUP BY and a subquery, but I simply cannot get it to work.

Here is a test database on SQL Fiddle: http://sqlfiddle.com/#!2/881cae/3

I realize there are a lot of similar questions on here, but I have read many of them and haven't been able to solve my problem, so I would appreciate direct help instead of just crying "duplicate!" and linking to another post. Thank you.

EDIT: SQL Fiddle seems to be down at the moment, so here is the database schema I had on there:

CREATE TABLE products
(
  id int auto_increment primary key, 
  name varchar(20)
);

INSERT INTO products
(
  name
)
VALUES
('product 1'),
('product 2');


CREATE TABLE product_prices
(
  id int auto_increment primary key, 
  p_id int, 
  price decimal(10,2),
  date_added int
);

INSERT INTO product_prices
(
  p_id, 
  price, 
  date_added
)
VALUES
(1, 1.99, 1000),
(1, 2.99, 2000),
(1, 3.99, 3000),
(1, 4.99, 4000),
(1, 5.99, 5000),
(1, 6.99, 6000),


(2, 1.99, 1000),
(2, 2.99, 2000),
(2, 3.99, 3000),
(2, 4.99, 4000),
(2, 5.99, 5000),
(2, 6.99, 6000);

Here is how you can do it:

SELECT pp.*
FROM product_prices pp
JOIN (
    SELECT p_id, MAX(date_added) as max_date
    FROM product_prices
    GROUP BY p_id
) x ON pp.p_id = x.p_id AND pp.date_added = x.max_date

The idea is to make a set of tuples {p_id, max_date} for each product id (that's the inner query) and filter the product_prices data using these tuples (that's the ON clause in the inner join).

Demo on sqlfiddle.

SELECT
distinct on(p_id)
price,
date_added 
FROM product_prices
ORDER BY p_id, date_added DESC

OR

SELECT
price
date_added 
FROM product_prices

join (
SELECT
p_id
max(date_added) as max_date
FROM product_prices
group by p_id
) as last_price on last_price.p_id = product_prices.p_id
and last_price.max_date = product_prices.date_added

neither tested so might contain a bug or two

Give it a go, although it's not an elegant solution:

SELECT pp1.price, pp1.date_added 
FROM product_prices pp1
WHERE pp1.date_added IN (SELECT MAX(pp2.date_added)
FROM product_prices pp2 WHERE pp2.p_id =  pp1.p_id )

Group by pp1.p_ID
Select price, date_added from product_prices 
where date_added =
(select max(date_added)
from product_prices
group by p_id)

is this what you want?

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