0

here is the table:

create table video_call (
timestamp timestamp,
callerid int,
receiverid int,
call_length int);

insert into video_call values
('2018-12-12 01:01:01', 1, 2, 3),
('2019-01-01 01:01:01', 1, 3, 5),
('2019-01-01 01:01:01', 2, 4, 3),
('2019-01-01 01:01:01', 5, 6, 3),
('2019-01-02 01:01:01', 3, 4, 3),
('2019-01-03 01:01:01', 3, 5, 3),
('2019-01-04 01:01:01', 3, 7, 3);

Now I'd like to get the new users on day 2019-01-01. Here is my answer:

select user from
(select distinct callerid as user from video_call where to_char(timestamp, 'YYYY-MM-DD') = '2019-01-01'
union
select distinct receiverid as user from video_call where to_char(timestamp, 'YYYY-MM-DD') = '2019-01-01') as t
where user not in 
(select distinct callerid as user from video_call where to_char(timestamp, 'YYYY-MM-DD') < '2019-01-01'
union
select distinct receiverid as user from video_call where to_char(timestamp, 'YYYY-MM-DD') < '2019-01-01');

then get this error:

ERROR:  operator does not exist: name = integer
LINE 5: where user not in 
                   ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 250

any idea of this? I already checked that all the subqueries work. Thanks

2 Answers 2

1

user is a reserved word which resolves to the name of the currently logged-in PostgreSQL user. You can see this by doing something like:

select user from
(select distinct callerid as user from video_call where to_char(timestamp, 'YYYY-MM-DD') = '2019-01-01') as t;
  user  
--------
 jjanes
 jjanes
 jjanes

To have it refer to a table column alias spelled "user", you need to qualify it with a table name, or put it in double quotes, or better yet just spell it differently to start with.

Sign up to request clarification or add additional context in comments.

Comments

0

I would suggest writing this as:

select v.userid
from video_call vc cross join lateral
     (values (vc.callerid), (vc.receiverid)) v(userid)
where timestamp < '2019-01-02'
group by v.userid
having min(timestamp) >= '2019-01-01';

It seems like a much simpler approach and should get around your syntax issues.

4 Comments

This approach is very cool! but I'm not familiar with lateral. Is that an in-built function?
when I run your solution, I get this error: ERROR: syntax error at or near "user" LINE 3: (values (vc.callerid), (vc.receiverid)) v(user) ^ SQL state: 42601 Character: 100 then I change user to users and it works!
Did some research and looks like lateral is SQL foreach and it can access to the query result preceding it. and values can create tmp table without insert. Learned a lot from your solution. Thanks @Gordon Linoff!
user is a Postgres reserved word. You shouldn't use it as a column name. I just figured it was a name used only in the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.