Postgres handle constraint conflict then insert excluded row - postgresql

If I have a table something like:
MyTable
id date value replaced_by_id
1 2020-01-01 10
2 2020-01-02 20 3
3 2020-01-02 21
With a unique constraint on date and replaced_by
e.g.
CREATE UNIQUE INDEX my_table_null_test ON my_table (date, (replaced_by_id is null))
WHERE replaced_by_id IS NULL;
How can I create an insert statement that sets the conflicting row's replaced_by_id to the the new rows id and then inserts the new row afterwards?
Along the lines of
insert into my_table (id, date, value) values (gen_id(), '2020-01-02', 21)
on conflict (date, (replaced_by_id is null) ) where replaced_by_id is null
do update
set replaced_by_id = excluded.id
**now insert the new row (insert the excluded row)**
for say the file the values are coming from a file that had many values for the same date. e.g.
date value
2020-01-01 10
2020-01-02 20
2020-01-02 21
2020-01-02 22
2020-01-02 23
2020-01-02 24
2020-01-02 22
would result in
MyTable
id date value replaced_by_id
1 2020-01-01 10
2 2020-01-02 20 3
3 2020-01-02 21 4
4 2020-01-02 22 5
5 2020-01-02 23 6
6 2020-01-02 24 7
7 2020-01-02 22

I think you can not use UPSERT for this requirement because UPSERT will perform only update operation on same table or DO Nothing.
Reason is:
You have added unique index which will prevent the insertion with combination of existing date and null of replace_by_id field.
You are trying to get the ID to update the existing records before insertion which is not possible.
So you have to use some workaround for it:
Using Triggers - You have to use 2 triggers on your table one is before insert and one is after insert like below:
Before Insert Trigger
Trigger Function
CREATE FUNCTION trig_beforeinsert()
RETURNS trigger
LANGUAGE 'plpgsql'
AS $BODY$
declare
flg int :=0;
begin
flg=(select count(*) from my_table where date_=new.date_ and replaced_by_id is null);
if flg>0 then
new.replaced_by_id=0;
end if;
return new;
end;
$BODY$;
Trigger on Table
CREATE TRIGGER my_table_before_insert
BEFORE INSERT
ON my_table
FOR EACH ROW
EXECUTE PROCEDURE trig_beforeinsert();
After Insert Trigger
Trigger Function
CREATE FUNCTION trig_afterinsert()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
declare
flg int :=0;
begin
if new.replaced_by_id = 0 then
UPDATE my_table set replaced_by_id=new.id where date_=new.date_ and replaced_by_id is null;
UPDATE my_table set replaced_by_id=null where id=new.id;
end if;
return new;
end;
$BODY$;
Trigger on Table
CREATE TRIGGER my_table_after_insert
AFTER INSERT
ON public.my_table
FOR EACH ROW
EXECUTE PROCEDURE public.trig_afterinsert();
DEMO

Related

How do I cap number of rows in based on category using postgres policies?

I have a database of orders and each order has a time_slot (of type TIME).
select id, time_slot from orders limit 5;
10 | 13:00:00
11 | 12:00:00
13 | 11:00:00
14 | 12:30:00
15 | 11:30:00
I want to make sure that only a certain number of orders can be placed in a time slot; for example, let's say I only want 8 orders per time slot.
I am using Supabase, so I would like to implement using RLS policies.
I've been through several iterations, but none of them have worked. Some complain of infinite recursion. My current approach is the following: I have created a view of time slot load.
create or replace view time_slot_load as
select time_slot, count(*)
from orders
group by time_slot;
select * from time_slot_load limit 5;
11:00:00 | 1
12:30:00 | 1
11:30:00 | 1
13:00:00 | 1
12:00:00 | 7
I can then create a policy that checks against this view.
ALTER POLICY "Only 8 orders per time slot"
ON public.orders
WITH CHECK (
(SELECT (load.count <= 8)
FROM time_slot_load load
WHERE (load.time_slot = orders.time_slot))
);
But this is not working.
Is there some way I can do this using constraints or RLS policies?
Any help is appreciated.
demo
table structure:
begin;
create table orders_count(
time_slot tstzrange ,
order_count integer default 0,
constraint order_ct_max1000 check(order_count <=4));
create table
orders(orderid int primary key, realtimestamp timestamptz , order_info text);
with a as(
SELECT x as begin_,x + interval '1 hour' as end_
FROM generate_series(
timestamp '2022-01-01',
timestamp '2022-01-02',
interval '60 min') t(x))
insert into orders_count(time_slot)
select tstzrange(a.begin_, a.end_,'[]') from a;
commit;
two table, one table for all the orders info, another table is track the timeslot's count, also make one constraint, within one timeslot no more than 4 orderid.
Then create trigger for delete/update/insert action on table orders.
for table orders_count, 20 years only 175200 rows (one hour one row).
main trigger function:
begin;
create or replace function f_trigger_orders_in()
returns trigger as
$$
begin
update orders_count set order_count = order_count + 1
where time_slot #> NEW.realtimestamp;
return null;
end;
$$ language plpgsql;
create or replace function f_trigger_orders_up()
returns trigger as
$$
begin
if OLD.realtimestamp <> NEW.realtimestamp THEN
update orders_count
set order_count = order_count -1
where time_slot #> OLD.realtimestamp;
update orders_count
set order_count = order_count + 1
where time_slot #> NEW.realtimestamp;
end if;
return null;
end
$$ language plpgsql;
create or replace function f_trigger_order_delaft()
returns trigger as
$$
BEGIN
update orders_count set order_count = order_count -1 where time_slot #> OLD.realtimestamp;
return null;
end;
$$
language plpgsql;
triggers action:
create trigger trigger_in_orders
AFTER INSERT ON public.orders FOR EACH ROW execute procedure f_trigger_orders_in();
create trigger trigger_up_orders
after update on public.orders for each row execute procedure f_trigger_orders_up();
create trigger trigger_del_orders
AFTER DELETE ON public.orders FOR EACH ROW execute procedure f_trigger_order_delaft();
I want to make sure that only a certain number of orders can be placed
in a time slot; for example, let's say I only want 8 orders per time
slot.
You cannot do that in PostgreSQL.
https://www.postgresql.org/docs/current/sql-createpolicy.html
check_expression:
Any SQL conditional expression (returning boolean). The conditional
expression cannot contain any aggregate or window functions. This
expression will be used in INSERT and UPDATE queries against the table
if row-level security is enabled. Only rows for which the expression
evaluates to true will be allowed. An error will be thrown if the
expression evaluates to false or null for any of the records inserted
or any of the records that result from the update. Note that the
check_expression is evaluated against the proposed new contents of the
row, not the original contents.
Why view won't work:
https://www.postgresql.org/docs/current/sql-createview.html
see Updatable Views section:
A view is automatically updatable if it satisfies all of the following
conditions:
The view's select list must not contain any aggregates, window functions or set-returning functions.

Create multiple records automatically in postgres?

Is there a way for postgres to automatically generate child records with set parameters? I'm basically trying to create an employee timesheet and each time a new timesheet for a given date is created, I'd like to create a 7 child records (one record for each day of that given week for the user to fill in)
Something like this:
date (automatically generated on a weekly basis) | hours | timesheet_id(FK) | project_id(FK)
2019-01-01 8 1 2
2019-01-02 10 1 2
2019-01-03 8 1 2
2019-01-04 8 1 2
2019-01-05 0 1 2
2019-01-06 0 1 2
2019-01-07 9 1 2
#Z4-tier is correct but the trigger function does not need a loop as it can be reduced to a single insert statement.
create or replace function create_timesheet_days()
returns trigger
language 'plpgsql'
as $$
begin
insert into timesheet_days(timesheet_id, week_day)
select new.timesheet_id, wk_day
from generate_series (new.timesheet_date, new.timesheet_date+interval '6 day', interval '1 day') wk_day;
return new;
end;
$$ ;
as mentioned in the comments, this is a textbook case for using triggers.
You'll need a procedure that handles creating the new records. This might work:
create or replace function create_timesheet_days()
returns trigger as $BODY$
declare counter INTEGER := 0;
begin
while counter < 6 loop
insert into my_schema.timesheet_week
(timesheet_date, hrs, timesheet_id, project_id)
select
NEW.timesheet_date + counter as timesheet_date,
0 as hrs,
NEW.timesheet_id as timesheet_id,
project.project_id as project_id
from my_schema.project;
counter := counter + 1;
end loop;
return NEW;
END;
$BODY$
language 'plpgsql';
Then you could create a trigger like this:
CREATE TRIGGER create_timsheet_days_trigger
BEFORE INSERT
ON my_schema.timesheet_week
FOR EACH ROW
EXECUTE PROCEDURE
create_timesheet_days();

Copy last row field value to another column table with trigger

I'm working in PostgreSQL using a trigger. I have 2 tables here, invoice_items and invoice. In the table 'invoice' data is inserted from the system, then the table 'invoice_items' is filled using a trigger to get the values from the inserted data of the table 'invoice'. Each insert from the system system consists of two rows like this:
table 'invoice':
id invoice_date statement amount
1 2018-10-03 Insert 5
2 2018-10-03 Update 6
then table 'invoice_items' after trigger the invoice data is inserted:
id total statement
1 5 Insert
2 6 Update
trigger:
create trigger do_fetch
after insert
on invoices
for each row
execute procedure insert_amount();
function insert_amount():
create function insert_amount()
returns trigger
language plpgsql
as $$
BEGIN
INSERT INTO invoice_items (total, statement) VALUES (new.amount, new.statement);
return null;
END;
$$;
But I just want to get last inserted data of 'invoices' to trigger 'invoice_items' to achieve a result like this:
id invoice_date statement amount
1 2018-10-03 Insert 5
2 2018-10-03 Update 6
id total statement
1 6 Update
I have tried to edit the trigger to this:
create constraint trigger do_fetch
after insert
on invoices
deferrable
for each row
execute procedure insert_amount();
but I still get 2 row inserted to 'invoice_items' table - not only the last row, any clue ? Thank you
Here is a example - you just need to adjust your sql with the desired tablenames and columnnames:
test=# create table bla1(ts timestamp, content text);
CREATE TABLE
test=*# create table bla1_log(ts timestamp, content text);
CREATE TABLE
test=*# create or replace function trg_bla1() returns trigger as $$begin insert into
bla1_log values (new.ts, new.content); return new; end; $$language plpgsql;
CREATE FUNCTION
test=*# create trigger trg1 after insert on bla1 for each row when (NEW.content =
'Update') execute procedure trg_bla1();
CREATE TRIGGER
test=*# insert into bla1 values (now(), 'bla');
INSERT 0 1
test=*# commit;
COMMIT
test=# insert into bla1 values (now(), 'Insert');
INSERT 0 1
test=*# commit;
COMMIT
test=# insert into bla1 values (now(), 'Update');
INSERT 0 1
test=*# select * from bla1;
ts | content
----------------------------+---------
2018-11-08 12:32:28.803439 | bla
2018-11-08 12:33:30.355516 | Insert
2018-11-08 12:33:38.451548 | Update
(3 rows)
test=*# select * from bla1_log ;
ts | content
----------------------------+---------
2018-11-08 12:33:38.451548 | Update
(1 row)
test=*#
EDIT:
As of your lack of replies and showing an effort to adjust your code according to my answer, I'm not sure if thats even worth my time - but here's what should work for you..
create table invoice(id serial, invoice_date text, statement text, amount integer);
create table invoice_items(id serial, total integer, statement text);
create or replace function insert_amount() returns trigger as $$begin
insert into invoice_items values (id, total, statement); return new; end;
create trigger mytrigger after insert on invoice for each row when (NEW.statement = 'Update') execute procedure insert_amount();

Postgresql same date record insert

I am using a Postgresql 9.5 database. A third party software application is also using this database. I have a Features table. I created an Events table to record Features events.
Features
------------
id name lon lat
1 x 0 10
2 y 15 20
When I create a record in the Features table, my trigger inserts a record into the Events table.
Events
id name date feature_id
1 insert 09.04.2018 14:22:23.065125 1
When I update Features name, lon and lat and save it, the software execution results in 3 update records at same time.
Events
id name date feature_id
1 insert 09.04.2018 14:22:23.065125 1
2 update 09.04.2018 18:15:41.099689 1
3 update 09.04.2018 18:15:41.099689 1
4 update 09.04.2018 18:15:41.099689 1
But this is 3 update is same values.
How can I restrict this in my trigger?
My trigger function:
CREATE FUNCTION event_fn() AS $BODY$ BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO events (event_name, event_date, feature_id) VALUES ('insert', now(), NEW.id);
RETURN NEW;
END IF;
IF TG_OP = 'UPDATE' THEN
INSERT INTO events (event_name, event_date, feature_id) VALUES ('update', now(), NEW.id);
RETURN NEW;
END IF;
IF TG_OP = 'DELETE' THEN
INSERT INTO events (event_name, event_date, feature_id) VALUES ('delete', now(), OLD.id);
RETURN OLD;
END IF;
END;
The best solution would be to opt out of the software that performs several updates instead of actually a single one. However, if you can not do this, you can add a trigger for the events table, e.g.:
create or replace function before_insert_on_events()
returns trigger language plpgsql as $$
begin
if exists (
select 1
from events e
where e.name = new.name
and e.date = new.date
and e.feature_id = new.feature_id)
then new = null;
end if;
return new;
end $$;
create trigger before_insert_on_events
before insert on events
for each row
execute procedure before_insert_on_events();

Update tables logic

I have two tables with triggers on them.
FIRST
CREATE OR REPLACE FUNCTION update_table()
RETURNS trigger AS
$BODY$
BEGIN
IF TG_OP = 'UPDATE' THEN
UPDATE filedata SET id=NEW.id,myData=NEW.myData,the_geom=ST_TRANSFORM(NEW.the_geom,70066) WHERE num=NEW.num;
RETURN NEW;
ELSEIF TG_OP = 'INSERT' THEN
INSERT INTO filedata(num,id,myData,the_geom) VALUES (NEW.num,NEW.id,NEW.myData,ST_TRANSFORM(NEW.the_geom,70066));
INSERT INTO filestatus(id,name,status) VALUES (NEW.num,NEW.myData,'Не подтвержден');
RETURN NEW;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
SECOND
CREATE OR REPLACE FUNCTION update_table_temp()
RETURNS trigger AS
$BODY$
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO filedata_temp(num,id,myData,the_geom) VALUES (NEW.num,NEW.id,NEW.myData,ST_TRANSFORM(NEW.the_geom,900913));
RETURN NEW;
ELSEIF TG_OP = 'DELETE' THEN
DELETE FROM filedata_temp WHERE num=OLD.num;
RETURN OLD;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
And I have a problem. If I insert data in the first table its trigger inserts data in the second table too. But that insert causes the second table's trigger to do an insert on the first table, and so on.
Can you help me with this? How to can I get the tables to update each other without looping?
UPDATE
i have another problem
How to change data when i INSERT it in table? For example i insert GEOMETRY in the_geom column. And if geometry's SRID=70066 i want to put in the_geom column result of working of this function ST_TRANSFORM(the_geom,900913).
UPDATE 2
trigger
CREATE TRIGGER update_geom
AFTER INSERT
ON filedata_temp
FOR EACH ROW
EXECUTE PROCEDURE update_geom();
function
CREATE OR REPLACE FUNCTION update_geom()
RETURNS trigger AS
$$
BEGIN
IF ST_SRID(NEW.the_geom)=70066 THEN
UPDATE filedata_temp SET id='88',the_geom=ST_TRANSFORM(NEW.the_geom,900913);
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
If i use this function trigger no work but if this:
CREATE OR REPLACE FUNCTION update_geom()
RETURNS trigger AS
$$
BEGIN
UPDATE filedata_temp SET id='88',the_geom=ST_TRANSFORM(NEW.the_geom,900913);
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
i get id=88 but ST_TRANSFORM not work.
UPDATE 3
ST_TRANSFORM() nice function but its do something strange in my case.
For example i have a table filedata_temp(SRID=4326). I Insert geometry with srid=70066 i try this trigger
CREATE OR REPLACE FUNCTION update_geom()
RETURNS trigger AS
$$
BEGIN
UPDATE filedata_temp the_geom=ST_TRANSFORM(NEW.the_geom,4326);
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
And get this geometry.
"0103000020E6100000010000001800000097832C7ABD823741DA312CBF59F6174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174115B8A7F8208337416DE8C689ADF7174115B8A7F8208337416DE8C689ADF71741D1D3BAF56383374114BFD1303AF917418B016D395F8537413C2856DFF7F717413AF95F044C853741A997BC22A3F71741F88E75BD2D85374178C92D9BE6F61741F92A3B192685374165C8D76E31F61741C84AA37B26853741F2674F6A96F5174144F25B9B16853741E849D10C1BF5174105142CD2E384374112E19E8688F31741B72C78F697843741A808260138F31741FF0C0C6A0884374151A8BBFF76F21741832CF2EEF48337418BE15C1290F21741FFFB3AC6A3833741D85A253DF4F2174113E8B8956C83374109067F2139F31741E383648E3383374100C25C64D8F3174179BAEBD7178337412DA0D6482BF41741CF38E4F7038337410AB04BD7E5F41741C936158CE182374145C1EC5D99F5174197832C7ABD823741DA312CBF59F61741"
ST_transform() make this string from SRID=4326 and geometry which transform in EPSG:70066.
There is this string in 70066
"0103000020B2110100010000001800000097832C7ABD823741DA312CBF59F6174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174115B8A7F8208337416DE8C689ADF7174115B8A7F8208337416DE8C689ADF71741D1D3BAF56383374114BFD1303AF917418B016D395F8537413C2856DFF7F717413AF95F044C853741A997BC22A3F71741F88E75BD2D85374178C92D9BE6F61741F92A3B192685374165C8D76E31F61741C84AA37B26853741F2674F6A96F5174144F25B9B16853741E849D10C1BF5174105142CD2E384374112E19E8688F31741B72C78F697843741A808260138F31741FF0C0C6A0884374151A8BBFF76F21741832CF2EEF48337418BE15C1290F21741FFFB3AC6A3833741D85A253DF4F2174113E8B8956C83374109067F2139F31741E383648E3383374100C25C64D8F3174179BAEBD7178337412DA0D6482BF41741CF38E4F7038337410AB04BD7E5F41741C936158CE182374145C1EC5D99F5174197832C7ABD823741DA312CBF59F61741"
And in 4326
"0103000020E61000000100000018000000AE4F5BA2FC5B4E407E80E7E6F46C4C40F7F1BF79255C4E4019C32D62086D4C40F7F1BF79255C4E4019C32D62086D4C40F7F1BF79255C4E4019C32D62086D4C40A7CE9382325C4E40D8EA369C0D6D4C40A7CE9382325C4E40D8EA369C0D6D4C401BD2B101575C4E4064A420982A6D4C4090DF29FE665D4E4064EE5369116D4C408195B3905C5D4E403664043C0B6D4C4025A00D0E4C5D4E40F7FD7274FD6C4C404201C7B5475D4E409ADF7B26F06C4C403801C7B5475D4E40E43D0EBFE46C4C406EC339053F5D4E404085D2B7DB6C4C40BDFDA836235D4E4001EBC841BE6C4C40685B445FFA5C4E4015C4038EB86C4C40ADB5C108AD5C4E40727935C6AA6C4C408A6B4B9BA25C4E40331ECEACAC6C4C40A7368928775C4E40F7C22E47B46C4C409F640F9D595C4E4077694F81B96C4C40660C21333B5C4E4012EA7C62C56C4C406623646D2C5C4E40CE83E38FCB6C4C4042D9EDFF215C4E40C6A89957D96C4C4095D75EC00F5C4E4013FFA0A5E66C4C40AE4F5BA2FC5B4E407E80E7E6F46C4C40"
You have mutually recursive triggers and you want to prevent the recursion. Your instead want a trigger to fire only on a direct action from a user, not an action via a trigger.
Unfortunately, PostgreSQL doesn't directly support what you want, you'll need to tweak your design to avoid the mutual recursion.
Updated question: In a trigger, alter the contents of NEW, eg
IF tg_op = 'INSERT' OR tg_op = 'UPDATE' THEN
NEW.the_geom := ST_TRANSFORM(NEW.the_geom,900913)
END IF;
See the really rather good manual for triggers.
-- The scenario is:
-- for UPDATEs we use an "alternating bit protocol"
-- (could also be done by bumping and synchronisng a serial number)
-- For INSERTs: we only test for NOT EXISTS.
-- DELETEs are not yet implemented.
-- *******************************************************************
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
--
-- Tables for test: we convert int <<-->> text
--
CREATE TABLE one
( id INTEGER NOT NULL PRIMARY KEY
, flipflag boolean NOT NULL default false
, ztext varchar
);
CREATE TABLE two
( id INTEGER NOT NULL PRIMARY KEY
, flipflag boolean NOT NULL default false
, zval INTEGER
);
------------------------
CREATE function func_one()
RETURNS TRIGGER AS $body$
BEGIN
IF tg_op = 'INSERT' THEN
INSERT INTO two (id,zval)
SELECT NEW.id, NEW.ztext::integer
WHERE NOT EXISTS (
SELECT * FROM two WHERE two.id = NEW.id)
;
ELSIF tg_op = 'UPDATE' THEN
UPDATE two
SET zval = NEW.ztext::integer
, flipflag = NOT flipflag
WHERE two.id = NEW.id
;
END IF;
RETURN NEW;
END;
$body$
language plpgsql;
CREATE TRIGGER trig_one_i
AFTER INSERT ON one
FOR EACH ROW
EXECUTE PROCEDURE func_one()
;
CREATE TRIGGER trig_one_u
AFTER UPDATE ON one
FOR EACH ROW
WHEN (NEW.flipflag = OLD.flipflag)
EXECUTE PROCEDURE func_one()
;
------------------------
CREATE function func_two()
RETURNS TRIGGER AS $body$
BEGIN
IF tg_op = 'INSERT' THEN
INSERT INTO one (id,ztext)
SELECT NEW.id, NEW.zval::varchar
WHERE NOT EXISTS (
SELECT * FROM one WHERE one.id = NEW.id)
;
ELSIF tg_op = 'UPDATE' THEN
UPDATE one
SET ztext = NEW.zval::varchar
, flipflag = NOT flipflag
WHERE one.id = NEW.id
;
END IF;
RETURN NEW;
END;
$body$
language plpgsql;
CREATE TRIGGER trig_two_i
AFTER INSERT ON two
FOR EACH ROW
EXECUTE PROCEDURE func_two()
;
CREATE TRIGGER trig_two_u
AFTER UPDATE ON two
FOR EACH ROW
WHEN (NEW.flipflag = OLD.flipflag)
EXECUTE PROCEDURE func_two()
; --
-- enter some data
--
INSERT INTO one (id,ztext)
select gs, gs::text
FROM generate_series(1,10) gs
;
-- Change some data
UPDATE one SET ztext=100 where id = 1;
UPDATE two SET zval=10*zval where id IN (2,4,6,8,10);
INSERT INTO two (id, zval) VALUES(11,14);
SELECT * FROM one ORDER BY id;
SELECT * FROM two ORDER BY id;
RESULT:
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "one_pkey" for table "one"
CREATE TABLE
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "two_pkey" for table "two"
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER
CREATE TRIGGER
CREATE FUNCTION
CREATE TRIGGER
CREATE TRIGGER
INSERT 0 10
UPDATE 1
UPDATE 5
INSERT 0 1
id | flipflag | ztext
----+----------+-------
1 | f | 100
2 | t | 20
3 | f | 3
4 | t | 40
5 | f | 5
6 | t | 60
7 | f | 7
8 | t | 80
9 | f | 9
10 | t | 100
11 | f | 14
(11 rows)
id | flipflag | zval
----+----------+------
1 | t | 100
2 | f | 20
3 | f | 3
4 | f | 40
5 | f | 5
6 | f | 60
7 | f | 7
8 | f | 80
9 | f | 9
10 | f | 100
11 | f | 14
(11 rows)