3
votes

I have two tables in postgres daily_report and summary_songs.

Sql file for creating the tables is here: https://nofile.io/f/Ef94rMFRh6C/file.sql

I want to update the summary_songs at the end of each day with below conditions:

  • If the userid already does not exist, then record from daily_report need to be inserted into summary_songs
  • If the userid exists, then summary_songs.countid = summary_songs.countid+ daily_report.countid.

I used below query to update summary_songs:

insert into summary_songs 
(select * from daily_report as B)
on conflict (userid, songd) 
do update set countid = countid+excluded.countid ;  

I get below error:

ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification

1

1 Answers

4
votes

To use on conflict you need to enforce a unique(userid, songd) on your summary_songs table:

SQL Fiddle

PostgreSQL 9.6 Schema Setup:

CREATE TABLE summary_songs (
    date_time date  NOT NULL,
    userid integer NOT NULL,
    songd integer NOT NULL,
    countid integer NOT NULL,
    unique(userid, songd) 
);


CREATE TABLE daily_report(
    date_time date NOT NULL,
    userid integer NOT NULL,
    songd integer NOT NULL,
    countid integer NOT NULL
);


insert into daily_report (date_time, userid, songd, countid) values
(to_date('2017-12-31','YYYY-MM-DD'),  1 ,     1 ,       5),
(to_date('2017-12-31','YYYY-MM-DD'),  2 ,     1 ,      10),
(to_date('2017-12-31','YYYY-MM-DD'),  4 ,     1 ,       7);


insert into summary_songs (date_time, userid, songd, countid) values
(to_date('2017-12-30', 'YYYY-MM-DD'),1, 1,  80),
(to_date('2017-12-30', 'YYYY-MM-DD'),2, 1,  51),
(to_date('2017-12-30', 'YYYY-MM-DD'),3, 1,  66);

Query 1:

select * from daily_report 

Results:

|  date_time | userid | songd | countid |
|------------|--------|-------|---------|
| 2017-12-31 |      1 |     1 |       5 |
| 2017-12-31 |      2 |     1 |      10 |
| 2017-12-31 |      4 |     1 |       7 |

Query 2:

select * from summary_songs 

Results:

|  date_time | userid | songd | countid |
|------------|--------|-------|---------|
| 2017-12-30 |      1 |     1 |      80 |
| 2017-12-30 |      2 |     1 |      51 |
| 2017-12-30 |      3 |     1 |      66 |

Query 3:

insert into summary_songs (date_time, userid, songd, countid)
select date_time, userid, songd, countid from daily_report
on conflict (userid, songd) 
do update set 
  countid = summary_songs.countid + excluded.countid ,
  date_time = excluded.date_time

Query 4:

select * from summary_songs 

Results:

|  date_time | userid | songd | countid |
|------------|--------|-------|---------|
| 2017-12-30 |      3 |     1 |      66 |
| 2017-12-31 |      1 |     1 |      85 |
| 2017-12-31 |      2 |     1 |      61 |
| 2017-12-31 |      4 |     1 |       7 |