Postgres, `where` condition, sort by first column, but I don't want that
You can do that if you change the way you pass the values to the WHERE clause. One way is to join to an unnested array and use the array index for sorting.

As you need a different sort order for the distinct on () you have to wrap the query in a derived table. The inner part uses an order by on the "distinct column". And the result can then be sorted by the array index.

select "HOBIS", "NAME", "URL", ... -- all columns but the `idx`
from (
  select distinct on ("HOBIS")
            product_shop_id as "HOBIS",
            ..., 
            x.idx
  ...
  from s_product
    join unnest(array['237002','230041','467173','464431']) with ordinality as x(shopid, idx) 
      on s_product.product_shop_id = x.shopid
    left join ...
    ...
  order by "HOBIS"
) t
order by t.idx


This behaves a bit different to an IN condition, so you have to make sure that every shop ID only appears once in the array.




  And why PG sort results when I have no sort condition in my sql?


Postgres does not sort your results. 

Without an order by clause, the database is free to return the rows in any order it wants. The "order" results from the different steps in the execution plan. If you see some perceived "order", then this probably stems from retrieving rows through an index. 

But the "order" you see there is in no way guaranteed. It can change because rows have been changed or inserted into the table, or because the query optimizer chooses to use a different execution plan. Or because some other transaction is running a similar statement.