Avoid duplication when using other table in WHERE and JOIN clause in Postgres
Use DISTINCT ON, it's considerably shorter, simpler and probably also faster:

SELECT DISTINCT ON (device_id) *
FROM   devices_shop_versions
WHERE  shop_id = 1
ORDER  BY device_id, updated_at DESC NULLS LAST;


Detailed explanation:


Select first row in each GROUP BY group?


If your table is big, you have many rows per device_id and you need to optimize performance, a recursive CTE might be faster, yet. Detailed instructions:


Optimize GROUP BY query to retrieve latest record per user


Make it a subquery to integrate in a bigger query:

SELECT mv.id, d.device_name, u.user_name, mv.version, mv.device_id, mv.shop_id, mv.updated_at
FROM  (
   -- query from above
   ) mv
JOIN   devices d on d.id = mv.device_id
JOIN   users   u on u.id = d.user_id
-- ORDER BY ???;  -- optional


Demo on rextester.

It's typically cheaper to join to more tables after excluding irrelevant rows.