How can I do a group-concat call with a max value?

时间:2018-06-25 19:43:37

标签: sql postgresql sqlite

I'm tracking game prices across multiple stores. I have a games table:

id | title       | platform_id
---|-------------|-----------
1  | Super Mario | 1
2  | Tetris      | 3
3  | Sonic       | 2

a stores table:

id | title       
---|-------------
1  | Target 
2  | Amazon      
3  | EB Games       

and a copies table with one entry for Target's copy of a given game, one entry for Amazon's, etc. I store the SKU so I can use it when scraping their websites.

game_id | store_id | sku
--------|----------|----------
1       | 2        | AMZ-3F4YK
1       | 3        | 001481

I run one scrape a day or a week or however long, and I store the result as cents in a prices table:

sku       | price   | time
----------|---------|------
AMZ-3F4YK | 4010    | 13811101
001481    | 3210    | 13811105

Plus a platforms table that just maps IDs to names.

Here's where I get confused and stuck.

I want to issue a query that selects each game, plus its most recent price at each store. So it would net results like

games.title | platform_name | info
------------|---------------|------
Super Mario | NES           | EB Games,1050;Amazon,3720;Target,5995
Tetris      | Game Boy      | EB Games,3720;Amazon,410;Target,5995

My best attempt thus far is

select
    games.title as title,
    platforms.name as platform,
    group_concat(distinct(stores.name) || "~" || prices.price) as price_info
from games
join platforms on games.platform_id = platforms.id
join copies on copies.game_id = games.id
join prices on prices.sku = copies.sku
join stores on stores.id = copies.store_id
group by title

Which nets results like

Super Mario | NES | EB Games~2300,Target~2300,Target~3800

that is, it includes every price listed, when I only want one per store (and for it to be the most recent). Figuring out how to integrate the 'select price where id = (select id from max(time)...' etc subquery to sort this out has totally stumped me all night and I'd appreciate any advice anyone could offer me.

I'm using SQLite, but if there's a better option in Postgres I could do it there.

1 个答案:

答案 0 :(得分:1)

您需要两个层次的聚合。 。 。而且,Postgres对此要简单得多,因此我将使用Postgres语法:

select title, platform,
       string_agg(s.name || '~' pr.price order by s.name)
from (select distinct on (g.title, p.name, s.name) g.title as title, p.name as platform, s.name, pr.price
      from games g join
           platforms p
           on g.platform_id = p.id join
           copies c
           on c.game_id = g.id join
           prices pr
           on pr.sku = c.sku join
           stores s
           on s.id = c.store_id
      group by g.title, p.name, s.name, pr.time desc
     ) gps
group by title, platform