Acho que isso corresponde ao seu resultado esperado:
select "user", "contact", "barcode", "date", "in", "out","dif"
, sum("in"-"out") over(partition by "user", "contact") as "sum"
from (
select "user", "contact", "barcode", "date", "in", "out","dif"
, lag(dif,1) over(partition by "user", "contact" order by "date" ASC) prevdif
, row_number() over(partition by "user", "contact" order by "date" DESC) rn
from "table1"
where date_trunc('day', "date") <= '2017-06-25' ::date - ( interval '1 week')::interval
and "date" > '2017-06-25'::date - ( interval '2 weeks')::interval
) d
where rn in (1,2) and prevdif is not null
order by 1,2,4 DESC
Resultado:
+----+-------+----------------+---------+---------------------+-----+-----+-----+-----+
| | user | contact | barcode | date | in | out | dif | sum |
+----+-------+----------------+---------+---------------------+-----+-----+-----+-----+
| 1 | USER2 | Guillermo Tole | 987654 | 16.06.2017 05:27:00 | 500 | 420 | 80 | 170 |
| 2 | USER2 | Guillermo Tole | 281460 | 15.06.2017 05:36:00 | 310 | 220 | 90 | 170 |
| 3 | USER3 | Juan Rulfo | 123456 | 15.06.2017 05:37:00 | 450 | 300 | 150 | 150 |
| 4 | USER3 | Pepito Marquez | 346234 | 15.06.2017 05:37:00 | 600 | 360 | 240 | 240 |
+----+-------+----------------+---------+---------------------+-----+-----+-----+-----+
Consulte:http://rextester.com/ISHS42170
Para condições como "mais recente", acho que usar ROW_NUMBER() OVER() é o mais conveniente, pois permite que toda a linha de cada evento "mais recente" seja retornada, o que não é tão simples se estiver usando MAX() e GRUPO POR. Resultados "distintos" são retornados filtrando as linhas com valor 1 retornado pela função.
+EDITAR
Em vez de usar
where rn in (1,2)
Acredito que uma maneira melhor seria usar o código de barras nas condições OVER(PARTITION BY...), assim:select "user", "contact", "barcode", "date", "in", "out","dif"
, sum("in"-"out") over(partition by "user", "contact") as "sum"
from (
select "user", "contact", "barcode", "date", "in", "out","dif"
, lag(dif,1) over(partition by "user", "contact", "barcode" order by "date" ASC) prevdif
, row_number() over(partition by "user", "contact", "barcode" order by "date" DESC) rn
from "table1"
where date_trunc('day', "date") <= '2017-06-25' ::date - ( interval '1 week')::interval
and "date" > '2017-06-25'::date - ( interval '2 weeks')::interval
) d
where rn = 1 and prevdif is not null
order by 1,2,4 DESC
http://rextester.com/SCV98254