Reformatting table in SQL - postgresql
I have a table in sql
Table Link
is there a way to reformat this table with contract_kind as rows and percentile values as columns without me having to create 4 tables with where clauses and joining them. Using Postgres.
TLDR: just use the crosstab function as per documentation
Long reply:
I recreated a similar case with
create table test (id int, contract_kind text, percentile int, cut_off_time float);
insert into test values
(1,'TEMPLATE',25,1.91),
(2,'TEMPLATE',50,51.93),
(3,'TEMPLATE',75,158.41),
(4,'TEMPLATE',90,343.01),
(5,'TEMPLATE_EDITABLE',25,26),
(6,'TEMPLATE_EDITABLE',50,27),
(7,'TEMPLATE_EDITABLE',75,28),
(8,'TEMPLATE_EDITABLE',90,29),
(9,'UPLOAD_EDITABLE',25,10),
(10,'UPLOAD_EDITABLE',50,20),
(11,'UPLOAD_EDITABLE',75,30),
(12,'UPLOAD_EDITABLE',90,40),
(13,'UPLOAD_SIGN',25,40),
(14,'UPLOAD_SIGN',50,77),
(15,'UPLOAD_SIGN',75,99),
(16,'UPLOAD_SIGN',90,133);
result:
id | contract_kind | percentile | cut_off_time
----+-------------------+------------+--------------
1 | TEMPLATE | 25 | 1.91
2 | TEMPLATE | 50 | 51.93
3 | TEMPLATE | 75 | 158.41
4 | TEMPLATE | 90 | 343.01
5 | TEMPLATE_EDITABLE | 25 | 26
6 | TEMPLATE_EDITABLE | 50 | 27
7 | TEMPLATE_EDITABLE | 75 | 28
8 | TEMPLATE_EDITABLE | 90 | 29
9 | UPLOAD_EDITABLE | 25 | 10
10 | UPLOAD_EDITABLE | 50 | 20
11 | UPLOAD_EDITABLE | 75 | 30
12 | UPLOAD_EDITABLE | 90 | 40
13 | UPLOAD_SIGN | 25 | 40
14 | UPLOAD_SIGN | 50 | 77
15 | UPLOAD_SIGN | 75 | 99
16 | UPLOAD_SIGN | 90 | 133
(16 rows)
Now to use the crosstab you need to create the tablefunc extension.
create extension tablefunc;
and then you can use it to pivot the data
select * from
crosstab('select percentile, contract_kind, cut_off_time from test order by 1,2')
as ct(percentile int, template float, template_editable float, upload_editable float, upload_sing float);
result
percentile | template | template_editable | upload_editable | upload_sing
------------+----------+-------------------+-----------------+-------------
25 | 1.91 | 26 | 10 | 40
50 | 51.93 | 27 | 20 | 77
75 | 158.41 | 28 | 30 | 99
90 | 343.01 | 29 | 40 | 133
(4 rows)
Related
rank function with limits in postgresql
select * from rankings; students | stu_id | card_id ----------+--------+--------- Charlie | 11 | 1 Shakira | 22 | 2 Selena | 33 | 3 Ross | 44 | 4 Chandler | 55 | 5 James | 66 | 6 Kylie | 77 | 7 Here is the table kindly tell me how we can apply the rank function in it with Postgresql?
postgrest retreive ranked results
I made a game, with level and scores saved into an sql table like this : create table if not exists api.scores ( id serial primary key, pseudo varchar(50), level int, score int, created_at timestamptz default CURRENT_TIMESTAMP ); I want to display the scores in the ui with the rank of each score, based on the score column, ordered by desc. Here is a sample data : id | pseudo | level | score | created_at ----+----------+-------+-------+------------------------------- 1 | test | 1 | 1 | 2020-05-01 11:25:20.446402+02 2 | test | 1 | 1 | 2020-05-01 11:28:11.04001+02 3 | szef | 1 | 115 | 2020-05-01 15:45:06.201135+02 4 | erg | 1 | 115 | 2020-05-01 15:55:19.621372+02 5 | zef | 1 | 115 | 2020-05-01 16:14:09.718861+02 6 | aa | 1 | 115 | 2020-05-01 16:16:49.369718+02 7 | zesf | 1 | 115 | 2020-05-01 16:17:42.504354+02 8 | zesf | 2 | 236 | 2020-05-01 16:18:07.070728+02 9 | zef | 1 | 115 | 2020-05-01 16:22:23.406013+02 10 | zefzef | 1 | 115 | 2020-05-01 16:23:49.720094+02 Here is what I want : id | pseudo | level | score | created_at | rank ----+----------+-------+-------+-------------------------------+------ 31 | zef | 7 | 730 | 2020-05-01 18:40:42.586224+02 | 1 50 | Cyprien | 5 | 588 | 2020-05-02 14:08:39.034112+02 | 2 49 | cyprien | 4 | 438 | 2020-05-01 23:35:13.440595+02 | 3 51 | Cyprien | 3 | 374 | 2020-05-02 14:13:41.071752+02 | 4 47 | cyprien | 3 | 337 | 2020-05-01 23:27:53.025475+02 | 5 45 | balek | 3 | 337 | 2020-05-01 19:57:39.888233+02 | 5 46 | cyprien | 3 | 337 | 2020-05-01 23:25:56.047495+02 | 5 48 | cyprien | 3 | 337 | 2020-05-01 23:28:54.190989+02 | 5 54 | Cyzekfj | 2 | 245 | 2020-05-02 14:14:34.830314+02 | 9 8 | zesf | 2 | 236 | 2020-05-01 16:18:07.070728+02 | 10 13 | zef | 1 | 197 | 2020-05-01 16:28:59.95383+02 | 11 14 | azd | 1 | 155 | 2020-05-01 17:53:30.372793+02 | 12 38 | balek | 1 | 155 | 2020-05-01 19:08:57.622195+02 | 12 I want to retreive the rank based on the full table whatever the result set. I'm using the postgrest webserver. How do I do that ?
You are describing window function rank(): select t.*, rank() over(order by score desc) rnk from mytable t order by score desc
Select rows by one column value should only be repeat N times
My table is: id sub_id datetime resource ---|-----|------------|------- 1 | 10 | 04/03/2009 | 399 2 | 11 | 04/03/2009 | 244 3 | 10 | 04/03/2009 | 555 4 | 10 | 03/03/2009 | 300 5 | 11 | 03/03/2009 | 200 6 | 11 | 03/03/2009 | 500 7 | 11 | 24/12/2008 | 600 8 | 13 | 01/01/2009 | 750 9 | 10 | 01/01/2009 | 760 10 | 13 | 01/01/2009 | 570 11 | 11 | 01/01/2009 | 870 12 | 13 | 01/01/2009 | 670 13 | 13 | 01/01/2009 | 703 14 | 13 | 01/01/2009 | 705 I need to select for each sub_id only 2 times Result would be: id sub_id datetime resource ---|-----|------------|------- 1 | 10 | 04/03/2009 | 399 3 | 10 | 04/03/2009 | 555 5 | 11 | 03/03/2009 | 200 6 | 11 | 03/03/2009 | 500 8 | 13 | 01/01/2009 | 750 10 | 13 | 01/01/2009 | 570 How can I achieve this result in postgres ?
Use the window function row_number(): select id, sub_id, datetime, resource from ( select *, row_number() over (partition by sub_id order by id) from my_table ) s where row_number < 3;
look at the order column (I use id to match your sample): t=# with data as (select *,count(1) over (partition by sub_id order by id) from t) select id,sub_id,datetime,resource from data where count <3; id | sub_id | datetime | resource ----+--------+------------+---------- 1 | 10 | 2009-03-04 | 399 3 | 10 | 2009-03-04 | 555 2 | 11 | 2009-03-04 | 244 5 | 11 | 2009-03-03 | 200 8 | 13 | 2009-01-01 | 750 10 | 13 | 2009-01-01 | 570 (6 rows)
Tibco Spotfire - Calculate average only if there are minimum 3 values in a column - see desc
I want to calculate average in Spotfire only when there are minimum 3 values. if there are no values or just 2 values the average should be blank Raw data: Product Age Average 1 2 3 10 4 12 5 13 11 6 7 18 8 19 9 20 19 10 21 20
The only way I could really do this is with 3 calculated columns. Insert these calculated columns in this order: If(Min(If([Age] IS NULL,0,[Age])) over (LastPeriods(3,[Product]))<>0,1) as [BitFlag] Avg([Age]) over (LastPeriods(3,[Product])) as [TempAvg] If([BitFlag]=1,[TempAvg]) as [Average] This will give you the following results. You can ignore / hide the two columns you don't care about. RESULTS +---------+-----+---------+------------------+------------------+ | Product | Age | BitFlag | TempAvg | Average | +---------+-----+---------+------------------+------------------+ | 1 | | | | | | 2 | | | | | | 3 | 10 | | 10 | | | 4 | 12 | | 11 | | | 5 | 13 | 1 | 11.6666666666667 | 11.6666666666667 | | 6 | | | 12.5 | | | 7 | 18 | | 15.5 | | | 8 | 19 | | 18.5 | | | 9 | 20 | 1 | 19 | 19 | | 10 | 21 | 1 | 20 | 20 | | 11 | | | 20.5 | | | 12 | 22 | | 21.5 | | | 13 | 36 | | 29 | | | 14 | | | 29 | | | 15 | 11 | | 23.5 | | | 16 | 23 | | 17 | | | 17 | 14 | 1 | 16 | 16 | +---------+-----+---------+------------------+------------------+
org mode - simplify table sum formula of multiple column
Now I need 5 formula for sum of each column, it works fine but I wish it can be simplified to one formula. Is it possible? |----+----+----+-----+----| | a | b | c | d | e | |----+----+----+-----+----| | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 | | 11 | 12 | 13 | 14 | 15 | | 16 | 17 | 18 | 19 | 20 | |----+----+----+-----+----| | 34 | 38 | 42 | 160 | 50 | |----+----+----+-----+----| #+TBLFM: #>$5=vsum(#2$5..#-1$5)::#>$4=vsum(#2$1..#-1$4)::#>$3=vsum(#2$3..#-1$3)::#>$2=vsum(#2$2..#-1$2)::#>$1=vsum(#2$1..#-1$1)
This should work: |----+----+----+----+----| | a | b | c | d | e | |----+----+----+----+----| | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 | | 11 | 12 | 13 | 14 | 15 | | 16 | 17 | 18 | 19 | 20 | |----+----+----+----+----| | 34 | 38 | 42 | 46 | 50 | |----+----+----+----+----| #+TBLFM: #>$1..#>$5=vsum(#2$0..#-1$0) $0 on the RHS is the current column.