简体   繁体   中英

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

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.

You need two levels of aggregation . . . And, Postgres is much simpler for this, so I'll use Postgres syntax:

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

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