SUM the same field on different CASE conditions - postgresql

I have a table with the following fields.
code quantity active
1 23 true
1 35 true
1 25 false
1 37 false
2 30 true
2 43 true
2 43 false
2 45 true
3 49 false
3 26 false
3 30 true
3 46 false
3 46 false
3 27 true
4 42 false
4 23 false
4 48 true
4 35 false
4 45 true
and I have the following query:
SELECT code, CASE WHEN active THEN COUNT(*) ELSE 0 END AS "activeCodes",
CASE WHEN active=false THEN COUNT(*) ELSE 0 END AS "inactiveCodes"
FROM tbl_codes
GROUP BY code, active
ORDER BY code
and the result of it is the following table:
code activeCodes inactiveCodes
1 0 2
1 2 0
2 3 0
2 0 1
3 0 4
3 2 0
4 0 3
4 2 0
but the result that I expected is
code activeCodes inactiveCodes
1 2 2
2 3 1
3 4 2
4 2 3
which condition am I missing here? how can I get the result that I expected?

You have a sparse matrix which you can collapse by running a SUM. Probably something like this (not tested):
SELECT code
,SUM(CASE WHEN active THEN 1 ELSE 0 END) AS "activeCodes"
,SUM(CASE WHEN active=false THEN 1 ELSE 0 END) AS "inactiveCodes"
FROM tbl_codes
GROUP BY code
ORDER BY code

Related

Adding 0 for missing data rather than excluding the category in matlab

I have the two following tables of data, one named data1, the other named data2. The left-hand column is a categorical variable and the right hand column is frequency I would like to rewrite these tables but where there are missing categories in the left-hand column I would like it to put in the correct missing category and then put a '0' in the right-hand frequency column.
data1 = [
1 170
2 120
3 100
4 40
5 30
6 20
7 10
9 8
10 2
11 1
14 1
];
data2 = [
1 240
2 200
3 180
4 60
5 50
6 40
7 30
8 20
9 8
10 2
12 1
19 1
];
To be clearer I will explain with an example. In data1, 8 12 and 13 are missing in the left-hand column. I would like matlab to recreate this table but with 0 values for 8, 12 and 13 so it looks as follows. I would also like it to have additional empty categories after '14' because data2 is longer and has more categories. I have also included what data2 should look like with filled in values.
data1 = [
1 170
2 120
3 100
4 40
5 30
6 20
7 10
8 0
9 8
10 2
11 1
12 0
13 0
14 1
15 0
16 0
17 0
18 0
19 0
];
data2 = [
1 240
2 200
3 180
4 60
5 50
6 40
7 30
8 20
9 8
10 2
11 0
12 1
13 0
14 0
15 0
16 0
17 0
18 0
19 1
];
I have a handful of datasets which generally all start with 1,2,3,4,5...etc but then they all have slightly different categories on the left-hand column, because where values are missing it just omits the category rather than putting 0. How do i write a code so that it automatically fills in any blanks with a 0. It would be good if the code could identify what the 'highest' number of categories is amongst all the datasets and then fill in blanks based on this.
my aim is to put together a grouped bar chart with data series that are all the same length.
UPDATED OUTPUT WITH 3 DATASETS
this is what your AllJoins code outputs in my matlab:
A table1 table2 table3
__ ______ ______ ______
1 170 240 2400
2 120 200 2000
3 100 180 0
4 40 60 0
5 30 50 0
6 20 40 0
7 10 30 0
8 0 20 0
9 8 8 0
10 2 2 0
11 1 0 0
12 0 1 0
14 1 0 0
19 0 1 0
20 0 0 1800
I would like the code to fill in the missing consecutive numbers in column A so that it looks as follows:
A table1 table2 table3
__ ______ ______ ______
1 170 240 2400
2 120 200 2000
3 100 180 0
4 40 60 0
5 30 50 0
6 20 40 0
7 10 30 0
8 0 20 0
9 8 8 0
10 2 2 0
11 1 0 0
12 0 1 0
13 0 0 0
14 1 0 0
15 0 0 0
16 0 0 0
17 0 0 0
18 0 0 0
19 0 1 0
20 0 0 1800
You can convert the datasets to a table and then use outerjoin. Then you can replace the NaNs with whatever you want using fillmissing.
table1 = array2table(data1);
table1.Properties.VariableNames = {'A', 'B'};
table2 = array2table(data2);
table2.Properties.VariableNames = {'A', 'B'};
newTable = outerjoin(table1, table2, 'LeftKeys', {'A'}, 'RightKeys', {'A'}, 'MergeKeys', true)
which produces:
A B_table1 B_table2
__ ________ ________
1 170 240
2 120 200
3 100 180
4 40 60
5 30 50
6 20 40
7 10 30
8 NaN 20
9 8 8
10 2 2
11 1 NaN
12 NaN 1
14 1 NaN
19 NaN 1
And then get your zeros with newTable2 = fillmissing(newTable, 'constant', 0), which prints:
A B_table1 B_table2
__ ________ ________
1 170 240
2 120 200
3 100 180
4 40 60
5 30 50
6 20 40
7 10 30
8 0 20
9 8 8
10 2 2
11 1 0
12 0 1
14 1 0
19 0 1
UPDATE
To combine multiple tables, you can either nest the outerjoin or write a function to loop over it (see similar Matlab forum question). Here's an example.
Given data1 and data2 in OP, plus a new data3:
data3 = [
1 2400
2 2000
20 1800
];
Contents of myscript.m:
table1 = MakeTable(data1);
table2 = MakeTable(data2);
table3 = MakeTable(data3);
AllJoins = MultiOuterJoin(table1, table2, table3);
% Functions
function Table = MakeTable(Array)
Table = array2table(Array);
Table.Properties.VariableNames = {'A', 'B'}; % set your column names, e.g. {'freq', 'count'}
end
function Joined = MultiOuterJoin(varargin)
Joined = varargin{1};
Joined.Properties.VariableNames{end} = inputname(1); % set #2 column name to be based on table name
for k = 2:nargin
Joined = outerjoin(Joined, varargin{k}, 'LeftKeys', {'A'}, 'RightKeys', {'A'}, 'MergeKeys', true);
name = inputname(k);
Joined.Properties.VariableNames{end} = name; % set merged column name to be based on table name
end
end
Which returns AllJoins:
A table1 table2 table3
__ ______ ______ ______
1 170 240 2400
2 120 200 2000
3 100 180 NaN
4 40 60 NaN
5 30 50 NaN
6 20 40 NaN
7 10 30 NaN
8 0 20 NaN
9 8 8 NaN
10 2 2 NaN
11 1 0 NaN
12 0 1 NaN
13 0 0 NaN
14 1 0 NaN
15 0 0 NaN
16 0 0 NaN
17 0 0 NaN
18 0 0 NaN
19 0 1 NaN
20 NaN NaN 1800
Feel free to change the maximum length of the array, this is a generic answer. The maximum length is max(data1(:,1)), but you can compute this in any way, e.g. the maximum value of multiple arrays.
% make new data
new_data1=zeros(max(data1(:,1),2));
new_data(:,1)=1:max(data1(:,1));
% Fill data. You can do this in a loop if its easier for you to understand.
% in essence, it says: in all the data1(:,1) indices of new_data's second column, put data1(:,2)
new_data(data1(:,1),2)=data1(:,2);

how to count a sequence(pattern) of numbers

I have table like this
ID
MW1
1
0
2
0
3
0
4
1
5
1
6
1
7
0
9
1
10
0
11
0
My output should look like this
ID
MW1
CountSequenz
1
0
1
2
0
1
3
0
1
4
1
2
5
1
2
6
1
2
7
0
3
9
1
4
10
0
5
11
0
5
The window functions would be a nice fit here.
Select ID
,MW1
,Seq = sum(Flg) over (order by ID)
From (
Select *
,Flg =case when lag(MW1,1) over (order by ID)=MW1 then 0 else 1 end
From YourTable
) A
Order by ID
Results

output for different changing variables

I have 4 variables a,b,c,d. a can vary 1,2 i.e. a=1,2, b=1,2,3, c=1,2,3,4, d=1,2,3,4,5 so by varying each element I want to make output value i.e.
a b c d output
1 1 1 1 1
1 1 1 2 2
1 1 1 3 3
1 1 1 4 4
1 1 1 5 5
now varying c with 1 value and d with all values i.e.
a b c d output
1 1 2 1 6
1 1 2 2 7
1 1 2 3 8
1 1 2 4 9
1 1 2 5 10
now change c to 3 and doing above so getting output as 11,12,13,14,15. when c reaches max varying limit then change b i.e.
a b c d output
1 2 1 1 16
1 2 1 2 17
1 2 1 3 18
1 2 1 4 19
1 2 1 5 20
then
a b c d output
1 2 2 1 21
1 2 2 2 22
1 2 2 3 23
1 2 2 4 24
1 2 2 5 25
so like this I want to proceed and want output for all conditions of a,b,c,d. so how to do it or any equation to do this in matlab. in above a,b,c,d vary 2,3,4,5 i.e in increasing order but in general case they can vary without increasing order e.g. a,b,c,d can vary 7,4,9,13.
A possible algorithm could be to buil the combinations column by column considering the number of times eache value has to be repeted starting form the array d
Defined:
len_a the length of the arraya
len_b the length of the arrayb
len_c the length of the arrayc
len_d the length of the arrayd
you need to replicate the d array len_a * len_b * len_c times.
The array c needs to be replicated len_c * len_d times to cover the "right side" combination, the this set of data have to be replicated len_a * len_b times to account for the "left side" to come.
Similar approach applies for the definiton of the array a and b.
To have the set of combinations in a "random" sequence, is sufficient to
use the randperm function.
% Define the input arrays
a=1:2;
len_a=length(a);
b=1:3;
len_b=length(b);
c=1:4;
len_c=length(c);
d=1:5;
len_d=length(d);
% Generate the fourth column of the table
%
d1=repmat(d',len_a*len_b*len_c,1)
%
% Generate the third column of the table
c1=repmat(reshape(bsxfun(#plus,zeros(len_d,1),[1:len_c]),len_c*len_d,1),len_a*len_b,1)
%
% Generate the second column of the table
b1=repmat(reshape(bsxfun(#plus,zeros(len_c*len_d,1),[1:len_b]),len_b*len_c*len_d,1),len_a,1)
%
% Generate the first column of the table
a1=reshape(bsxfun(#plus,zeros(len_b*len_c*len_d,1),[1:len_a]),len_a*len_b*len_c*len_d,1)
%
% Merge the colums and add the counter in the fifth column
combination_set_1=[a1 b1 c1 d1 (1:len_a*len_b*len_c*len_d)']
% Randomize the rows
combination_set_2=combination_set_1(randperm(len_a*len_b*len_c*len_d),:)
Output:
1 1 1 1 1
1 1 1 2 2
1 1 1 3 3
1 1 1 4 4
1 1 1 5 5
1 1 2 1 6
1 1 2 2 7
1 1 2 3 8
1 1 2 4 9
1 1 2 5 10
1 1 3 1 11
1 1 3 2 12
1 1 3 3 13
1 1 3 4 14
1 1 3 5 15
1 1 4 1 16
1 1 4 2 17
1 1 4 3 18
1 1 4 4 19
1 1 4 5 20
1 2 1 1 21
1 2 1 2 22
1 2 1 3 23
1 2 1 4 24
1 2 1 5 25
1 2 2 1 26
1 2 2 2 27
1 2 2 3 28
1 2 2 4 29
1 2 2 5 30
1 2 3 1 31
1 2 3 2 32
1 2 3 3 33
1 2 3 4 34
1 2 3 5 35
1 2 4 1 36
1 2 4 2 37
1 2 4 3 38
1 2 4 4 39
1 2 4 5 40
1 3 1 1 41
1 3 1 2 42
1 3 1 3 43
1 3 1 4 44
1 3 1 5 45
1 3 2 1 46
1 3 2 2 47
1 3 2 3 48
1 3 2 4 49
1 3 2 5 50
1 3 3 1 51
1 3 3 2 52
1 3 3 3 53
1 3 3 4 54
1 3 3 5 55
1 3 4 1 56
1 3 4 2 57
1 3 4 3 58
1 3 4 4 59
1 3 4 5 60
2 1 1 1 61
2 1 1 2 62
2 1 1 3 63
2 1 1 4 64
2 1 1 5 65
2 1 2 1 66
2 1 2 2 67
2 1 2 3 68
2 1 2 4 69
2 1 2 5 70
2 1 3 1 71
2 1 3 2 72
2 1 3 3 73
2 1 3 4 74
2 1 3 5 75
2 1 4 1 76
2 1 4 2 77
2 1 4 3 78
2 1 4 4 79
2 1 4 5 80
2 2 1 1 81
2 2 1 2 82
2 2 1 3 83
2 2 1 4 84
2 2 1 5 85
2 2 2 1 86
2 2 2 2 87
2 2 2 3 88
2 2 2 4 89
2 2 2 5 90
2 2 3 1 91
2 2 3 2 92
2 2 3 3 93
2 2 3 4 94
2 2 3 5 95
2 2 4 1 96
2 2 4 2 97
2 2 4 3 98
2 2 4 4 99
2 2 4 5 100
2 3 1 1 101
2 3 1 2 102
2 3 1 3 103
2 3 1 4 104
2 3 1 5 105
2 3 2 1 106
2 3 2 2 107
2 3 2 3 108
2 3 2 4 109
2 3 2 5 110
2 3 3 1 111
2 3 3 2 112
2 3 3 3 113
2 3 3 4 114
2 3 3 5 115
2 3 4 1 116
2 3 4 2 117
2 3 4 3 118
2 3 4 4 119
2 3 4 5 120
Hope this helps.
Qapla'

How can I make a diamond of zeroes in a matrix of any size? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a square Matrix N x M, odd dimensions, and I want to put a diamond of zeroes, for example, for a 5 x 5 matrix:
1 3 2 4 2
5 7 8 9 5
3 2 4 6 3
6 8 2 1 3
3 3 3 3 3
Is transform to:
1 3 0 4 2
5 0 8 0 5
0 2 4 6 0
6 0 2 0 3
3 3 0 3 3
How can this be done efficiently?
I'll bite, here is one approach:
% NxN matrix
N = 5;
assert(N>1 && mod(N,2)==1);
A = magic(N);
% diamond mask
N2 = fix(N/2);
[I,J] = meshgrid(-N2:N2);
mask = (abs(I) + abs(J)) == N2;
% fill with zeros
A(mask) = 0;
The result:
>> A
A =
17 24 0 8 15
23 0 7 0 16
0 6 13 20 0
10 0 19 0 3
11 18 0 2 9
I also had some time to play around. For my solution there are no limits concerning A being odd or even or larger than 1. Every integer is fine (even 0 works, though it does not make sense).
% NxN matrix
N = 7;
A = magic(N);
half = ceil( N/2 );
mask = ones( half );
mask( 1 : half+1 : half*half ) = 0;
mask = [ fliplr( mask ) mask ];
mask = [ mask; flipud( mask ) ];
if( mod(N,2) == 1 )
mask(half, :) = []
mask(:, half) = []
end
A( ~mask ) = 0;
A
I am first creating a square sub-matrix mask of "quarter" size (half the number of columns and half the number of rows, ceil() to get one more in the case N is odd).
Example for N=7 -> half=4.
mask =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
I then set it's diagonal values to zero:
mask =
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Mirror the mask horizontally:
mask =
1 1 1 0 0 1 1 1
1 1 0 1 1 0 1 1
1 0 1 1 1 1 0 1
0 1 1 1 1 1 1 0
Then mirror it vertically:
mask =
1 1 1 0 0 1 1 1
1 1 0 1 1 0 1 1
1 0 1 1 1 1 0 1
0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0
1 0 1 1 1 1 0 1
1 1 0 1 1 0 1 1
1 1 1 0 0 1 1 1
As N is odd we got a redundant row and redundant column that are then removed:
mask =
1 1 1 0 1 1 1
1 1 0 1 0 1 1
1 0 1 1 1 0 1
0 1 1 1 1 1 0
1 0 1 1 1 0 1
1 1 0 1 0 1 1
1 1 1 0 1 1 1
The logical not is then used as a mask to select the values in the original matrix that are set to 0.
Probably not as efficient as #Amro's solution, but it works. :D
My solution:
looking at the first left half of the matrix
in the first row 0 is in the middle column (let's call it mc)
in the second row the 0is in column mc-1
and so on while the rows increase
when you reach column 1 the sequence continue but with mc+1 but the rows decrease
In a similar way for the right half of the matrix
n=7
a=randi([20 30],n,n)
% Centre of the matrix
p=ceil(n/2)
% Identify the column sequence
col=[p:-1:1 2:p p+1:n n-1:-1:p]
% Identify the row sequence
row=[1:n n-1:-1:1]
% Transorm the row and column index in linear index
idx=sub2ind(size(a),row,col)
% Set the 0'
a(idx)=0
a =
22 29 23 27 27 21 23
29 29 21 27 24 26 24
30 28 21 27 29 28 25
28 22 24 20 27 24 25
23 26 21 20 30 20 29
26 20 26 23 25 22 25
21 24 25 25 23 21 30
a =
22 29 23 0 27 21 23
29 29 0 27 0 26 24
30 0 21 27 29 0 25
0 22 24 20 27 24 0
23 0 21 20 30 0 29
26 20 0 23 0 22 25
21 24 25 0 23 21 30
Hope this helps.
Qapla'
Using indexing (only works when N is odd):
N = 7;
% Random matrix
A = randi(100, N);
idx = [N-1:-2:1; 2:2:N];
A(cumsum([ceil(N/2) idx(:)' idx(end-1:-1:1)])) = 0
A =
60 77 74 0 54 83 9
8 48 0 76 0 28 67
6 0 32 78 83 0 10
0 27 25 5 11 39 0
76 0 49 43 67 0 16
79 7 0 86 0 70 78
57 28 85 0 81 44 81

Value comparison of matrix elements in MATLAB

Say I have a 256 by 256 matrix. I would like to replace any values that are 'greater' or 'equal' to 10 with 1 and make the rest 0 i.e. (values < 10).
For example,
2 3 6 15 24 32 1 7 39 10 ....
1 5 7 11 19 10 20 28 9 ........
10 24 6 29 10 25 32 10 ..........
.................................
.................................
and I want the output to be:
0 0 0 1 1 1 0 0 1 1 ............
0 0 0 1 1 1 1 1 0 ..............
1 1 0 1 1 1 1 1 ................
................................
................................
How can I do it?
Example:
a = [3 2 6 6 ;
7 5 3 7 ;
7 10 8 9 ;
2 4 3 10];
b = ( a > 5 )
b =
0 0 1 1
1 0 0 1
1 1 1 1
0 0 0 1