PostgreSQL, sum data from row of table? - postgresql

x a b c d
----------
A 1 2 3 4
B 5 6 7 8
C 6 7 8 9
I want my sum of A = 1 + 2 + 3 + 4 and so for B and C, Is there any command that can sum row of data in PostgreSQL?

There is no such built-in function, but you can simply do the following:
select x, a+b+c+d as column_sum from mytable
Assuming, of course, that the data type of a, b, c and d are numeric.

Related

SQL aggregate sum produces unexpected output

I don't understand how sum works.
For a PostgreSQL table in dbeaver:
a
b
c
d
1
2
3
2
1
2
4
3
2
1
3
2
2
1
4
2
3
2
4
2
the query
select a, b, c, d, sum(c) as sum_c, sum(d) as sum_d from abc a group by a, b, c, d
produces
a
b
c
d
sum_c
sum_d
1
2
3
2
3
2
1
2
4
3
4
3
2
1
3
2
3
2
2
1
4
2
4
2
3
2
4
2
4
2
and I don't understand why: I expected sum_c would be 18 in each row, which is the sum of values in c, and sum_d would be 11 for the same reason.
Why do sum_c and sum_d just copy the values from c and d in each row?
You can't get the result that you want with group by.
When you aggregate with group by you create groups for all the columns that are after group by and for each of these groups you get the aggregated results.
For your sample data, one group is 1,2,3,2 and for this combination of values you get the sum of c which is 3 since there is only 1 row with c=3 in that group.
Use SUM() window function:
SELECT a, b, c, d,
SUM(c) OVER () sum_c,
SUM(d) OVER () sum_d
FROM abc

SPSS Modeler group by and select top n rows

I would like to know what is the proper way in SPSS to group data by specydic column and then find top n max values.
For example I have below columns:
x<-c(3,2,1,8,7,11,10,9,7,5,4)
y<-c("a","a","a", "b","b","c","c","c","c","c","c")
z<-c(2,2,2,1,1,3,3,3,3,3,3)
I want to select top max n values from column X for each group by column y
x y
1 3 a
2 2 a
3 1 a
4 8 b
5 7 b
6 11 c
7 10 c 3
8 9 c 3
9 7 c 3
10 5 c 3
11 4 c 3

MATLAB sort matrix by one row

I have matrix lets say MAT of size 2*n
I want to sort the matrix by row num 2
BUT to keep each info from row 1 to its row 2 info
prev
C K A L E Y B
4 2 1 3 6 7 7
and after sort
A K L C E Y B
1 2 3 4 6 7 7
any idea?
you can use the second output argument of sort:
[~, si] = sort(MAT(2,:));
res = MAT(:,si);

Multiple Combinations of Values in Numerical Order

I have searched and attempted to solve this puzzle myself (I've gotten close, but I've had no luck). I have a large table of values (composed of Sets of Values) that can have multiple combinations, but those combinations must be returned in the ID order.
I have not been able to get this to work in SQL.
Example Set:
(Sorry I am not able to post an image which would explain it better so Ill keep it simple.)
Table[(ID, Value) {(1,A),(1,B),(1,C),(2,D),(3,F),(3,G), (4,J), (5,S),(5,T),(5,U))}
RESULTS
ID VALUE
1 A
2 F
3 G
4 J
5 S
1 A
2 F
3 G
4 J
5 T
1 A
2 F
3 G
4 J
5 U
1 A
2 F
3 H
4 J
5 S
1 A
2 F
3 H
4 J
5 T
1 A
2 F
3 H
4 J
5 U
1 B
2 F
3 G
4 J
5 S
1 B
2 F
3 G
4 J
5 T
1 B
2 F
3 G
4 J
5 U
1 B
2 F
3 H
4 J
5 S
1 B
2 F
3 H
4 J
5 T
1 B
2 F
3 H
4 J
5 U
1 C
2 F
3 G
4 J
5 S
1 C
2 F
3 G
4 J
5 T
1 C
2 F
3 G
4 J
5 U
1 C
2 F
3 H
4 J
5 S
1 C
2 F
3 H
4 J
5 T
1 C
2 F
3 H
4 J
5 U
Here's the problem in dynamic SQL without any cursors or loops.
IF OBJECT_ID('yourTable') IS NOT NULL
DROP TABLE yourTable;
CREATE TABLE yourTable (ID INT, Value CHAR(1));
INSERT INTO yourTable
VALUES (1,'A'),(1,'B'),(1,'C'),
(2,'D'),
(3,'F'),(3,'G'),
(4,'J'),
(5,'S'),(5,'T'),(5,'U');
DECLARE #row_number_cols VARCHAR(MAX),
#Aliased_Cols VARCHAR(MAX),
#Cross_Joins VARCHAR(MAX),
#Unpivot VARCHAR(MAX);
SELECT #row_number_cols = COALESCE(#row_number_cols + ',','') + col,
#Aliased_Cols = COALESCE(#Aliased_Cols + ',','') + CONCAT(col,' AS col',ID),
#Cross_Joins = COALESCE(#Cross_Joins,'') + CASE
WHEN ID = 1 THEN CONCAT(' FROM (SELECT * FROM yourTable WHERE ID = 1) AS ID',ID)
ELSE CONCAT(' CROSS JOIN (SELECT * FROM yourTable WHERE ID = ',ID,') AS ID',ID)
END,
#Unpivot = COALESCE(#Unpivot + ',','') + CONCAT('col',ID)
FROM yourTable A
CROSS APPLY (SELECT CONCAT('ID',ID,'.Value')) CA(col) --Just so I can reuse "col" in my code
GROUP BY A.ID,CA.col
SELECT #row_number_cols,#Aliased_Cols,#Cross_Joins,#Unpivot
SELECT
'WITH CTE_crossJoins
AS
(
SELECT ROW_NUMBER() OVER (ORDER BY ' + #row_number_cols + ') group_num,' + #Aliased_Cols +
#Cross_Joins + '
)
SELECT group_num,
val
FROM CTE_crossJoins
UNPIVOT
(
val for col IN (' + #Unpivot + ')
) unpvt
ORDER BY 1,2'
Results:
group_num val
-------------------- ----
1 A
1 D
1 F
1 J
1 S
2 A
2 D
2 G
2 J
2 S
3 A
3 D
3 G
3 J
3 T
4 A
4 D
4 F
4 J
4 T
5 A
5 D
5 F
5 J
5 U
6 A
6 D
6 G
6 J
6 U
7 B
7 D
7 G
7 J
7 S
8 B
8 D
8 F
8 J
8 S
9 B
9 D
9 F
9 J
9 T
10 B
10 D
10 G
10 J
10 T
11 B
11 D
11 G
11 J
11 U
12 B
12 D
12 F
12 J
12 U
13 C
13 D
13 F
13 J
13 S
14 C
14 D
14 G
14 J
14 S
15 C
15 D
15 G
15 J
15 T
16 C
16 D
16 F
16 J
16 T
17 C
17 D
17 F
17 J
17 U
18 C
18 D
18 G
18 J
18 U
I think this has been answered before here:
How to generate all possible data combinations in SQL?
difference being that they essentially dropped the ID column, should be easy to pull it through though.
You can employ the SQL windows function to achieve this.
;WITH CTE AS
(
SELECT Id,
Value,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) RN
FROM Tbl
)
SELECT * FROM CTE ORDER BY RN, ID, VALUE
Fiddle

Conditionally replacing cell values with column names

I have a 165 x 165 rank matrix such that each row has values ranging from 1-165. I want to parse each row and delete all values >= 5, sort each row in increasing order, then replace the values 1-5 with the name of the column from the original matrix.
For example, for row k the values 1 ,2 3, 4, 5, would result after the first two transformations and would be replaced by p,d, m, n, a.
I am assuming that your array consists of an array of arrays...
Neither Awk, Sed, or Perl have multi-dimensional arrays. However, they can be emulated in Perl by using arrays of arrays.
$a[0]->[0] = xx;
$a[0]->[1] = yy;
[...]
$a[0]->[164] = zz;
$a[1]->[0] = qq;
$a[1]->[1] = rr;
[...]
$a[164]->[164] = vv;
Does this make sense?
I'm calling the row $x and columns $y, so an element in your array will be $array[$x]->[$y]. Is that good?
Okay, your column names will be in row $array[0], so if we find a value less than five in $array[$x]->[$y], we know the column name is in $array[0]->[$y]. Is that good?
for my $x (1..164) { #First row is column names
for my $y (0..164) {
if ($array[$x]->[$y] <= 5) {
$array[$x]->[$y] = $array[0]->[$y];
}
}
}
I'm simply going through all the rows, and for each row, all the columns, and checking the value. If the value is less than or equal to five, I replace it with the column name.
I hope I'm not doing your homework for you.
This GNU sed solution might work although it will need scaling up as I only used a 10x10 matrix for testing purposes:
# { echo {a..j};for x in {1..10};do seq 1 10 | shuf |sed 'N;N;N;N;N;N;N;N;N;s/\n/ /g';done; }> test_data
# cat test_data
a b c d e f g h i j
4 5 9 3 6 2 10 8 7 1
3 7 4 2 1 6 10 5 8 9
10 9 3 1 2 7 8 5 6 4
5 10 4 9 7 8 1 3 6 2
8 6 5 9 1 4 3 2 7 10
2 8 9 3 5 6 10 1 4 7
3 9 8 2 1 4 10 6 7 5
3 7 2 1 8 6 10 4 5 9
1 10 8 3 6 5 4 2 7 9
7 2 3 5 6 1 10 4 8 9
# cat test_data |
sed -rn '1{h;d};s/[0-9]{2,}|[6-9]/0/g;G;s/\n|$/ &/g;s/$/&1 2 3 4 5 /;:a;s/^(\S*) (.*\n)(\S* )(.*)/\2\4\1\3/;ta;s/\n//;s/0[^ ]? //g;:b;s/([1-5])(.*)\1(.)/\3\2/;tb;p'
j f d a b
e d a c h
d e c j h
g j h c a
e h g f c
h a d i e
e d a f j
d c a h i
a h d g f
f b c h d
The sed command works as follows.
The first line of the data file contains the column headings is stored in the hold space then the pattern space (current line) is deleted. For all subsequent data lines all two or more digit numbers and values 6 to 9 are converted to 0. The column names are appended, along with a newline to the data values. Spaces are inserted before the newline and end of string. The data is transformed into a lookup and the sorted values i.e.. 1 2 3 4 5 is prepended to it. The newline is removed along with any 0 values and associated lookups. The values 1 to 5 are replaced by the column names in the lookup.
EDIT:
I may have misunderstood the problem regarding sorting columns or rows, if so it's a minimal fix - replace 1 2 3 4 5 by the original values and perform a numeric sort prior to replacing the numeric data with column names from the lookup.