Find the same values in two columns in Powershell? - powershell

I need to compare two columns in the datatable in Powershell. As result it should create 3 new datatables:
the same values in Column 1 and Column 2
only the values in Column 1
only the values in Column 2
Values are string values.
Column 1 | Column 2
---------|----------
Value 1 | Value 3
Value 2 | Value 4
Value 3 | Value 6
Value 4 | Value 7
Value 5 |
datatable_1:
Column 3
---------
Value 3
value 4
datatable_2:
Column 1
---------
Value 1
Value 2
Value 5
datateble_3:
Column 2
---------
Value 6
Value 7

$Table = ConvertFrom-SourceTable '
Column 1 | Column 2
---------|----------
Value 1 | Value 3
Value 2 | Value 4
Value 3 | Value 6
Value 4 | Value 7
Value 5 |'
PS C:\> $Table | Select 'Column 1' | Where {$Table.'Column 2' -Contains $_.'Column 1'}
Column 1
--------
Value 3
Value 4
PS C:\> $Table | Select 'Column 1' | Where {$Table.'Column 2' -NotContains $_.'Column 1'}
Column 1
--------
Value 1
Value 2
Value 5
PS C:\> $Table | Select 'Column 2' | Where {$Table.'Column 1' -NotContains $_.'Column 2'}
Column 2
--------
Value 6
Value 7

Related

KDB Select average of List data type for each row

Is there anyway in KDB to get the average of each row which has list data type ?
E.g. I have table with column ID and Size :
| ID | size |
|----|-----------|
| 1 | [1,3] |
| 2 | [3,3,3] |
| 3 | [4,2,4,2] |
In select , I want ID and avg of size :
| ID | avg |
|----|-----|
| 1 | 2 |
| 2 | 3 |
| 3 | 3 |
q)t:([]id:1 2 3;size:(1 3;3 3 3;4 2 4 2))
q)t
id size
----------
1 1 3
2 3 3 3
3 4 2 4 2
q)select id,avg each size from t
id size
-------
1 2
2 3
3 3

Postgres set jsonb field with columns from the same table

I am trying to move data from a couple of columns to a single JSONB column.
For example, I have x,y,z columns like this :
id | x | y | z | data
---------------------
1 | 1 | 2 | 3 | NULL
2 | 4 | 5 | 6 | NULL
3 | 7 | 8 | 9 | NULL
And I want to make it like that :
id | x | y | z | data
---------------------
1 | 1 | 2 | 3 | {"x":1, "y":2, "z": 3}
2 | 4 | 5 | 6 | {"x":4, "y":5, "z": 6}
3 | 7 | 8 | 9 | {"x":7, "y":8, "z": 9}
I tried unsuccessfully with jsonb_set and jsonb_insert. I am using postgresql 14.
You can convert the entire row to a json value, then remove the id column
select t.*,
to_jsonb(t) - 'id' as data
from the_table t;
OK, thanks to #Edouard I've made the query :
UPDATE table SET data = jsonb_build_object('x', x, 'y', y, 'z', z);
An update version of the solution by #a_horse_with_no_name:
update the_table set data = to_jsonb(the_table.*) - 'id' - 'data';
Unlike the jsonb_build_object approach it works w/o change for whatever number of columns except id and data.

Finding distinct values across multiple columns

I want to create a function that finds the the number of pno's with the sid (staff id) that have worked on it.
So for example if I wanted to find the sid's corresponding to pno = 1
select sid_worked_on(1)
count
-------
2
I would have 2 as sid 0 and 1 have worked on it.
This is the joined table from 3 different tables.
pno | a_sid | b_sid | c_sid
-----+--------+--------+--------
1 | 0 | 0 | 0
4 | 4 | 4 | 6
5 | 4 | 4 | 5
2 | 0 | 0 | 0
1 | 0 | 1 | 0
7 | 5 | 4 | 4
7 | 5 | 5 | 4
5 | 4 | 4 | 4
4 | 4 | 5 | 6
7 | 5 | 4 | 1
7 | 5 | 5 | 1
6 | 5 | 4 | 5
My only way of thinking how to do it would be to "flatten" the table into one column since there is no need for multiple columns and do distinct sid, but I haven't learnt how to do that yet.
pno | sid
-----+--------
1 | 0 |
4 | 4 |
5 | 4 |
2 | 0 |
1 | 0 |
7 | 5 |
7 | 5 |
5 | 4 |
4 | 4 |
7 | 5 |
7 | 5 |
6 | 5 |
--where the new table starts
1 | 0 |
4 | 4 |
5 | 4 |
2 | 0 |
1 | 1 |
7 | 4 |
...
...
I also thought to create a table and going through each value, so
create table
for each row where pno = 1
check if a_sid in table
if not then add a_sid to table
check if b_sid in table
if not then add b_sid to table
check if c_sid in table
if not then add c_sid to table
Would there be a better way of doing this?
Use UNION
SELECT pno, a_sid from table
UNION
SELECT pno, b_sid from table
UNION
SELECT pno, c_sid from table
Depending on whether you want duplicated entries of the same pno with the same column on the right side, you can use UNION ALL instead of UNION.
You can create a view with this query.

How print Horizontally on ireport dynamically while printing on next page when reached column limit for single page?

I think the the question can be reworded properly please kindly edit if necessary. I've also checked other questions and answers over the internet but it didn't help.
Below is what I'm trying to achieve, basically I want the columns to display horizontally; and if they reach lets say 3 columns(name) it will start on another page. These columns have subcolumns below.
I've already tried setting the Print Order to horizontal and set the columns to 3. However its showing the unexpected output.
This my table structure(These have thousands of records). I've also tried to turn this into array but it doesnt work.
How can I achieve the ouput above on the report? If you can provide documents or links about this is really helpful. Im using Postgres and ireport 3.7.6.
date | name
------+--------
1 | Name 1
2 | Name 1
3 | Name 1
4 | Name 1
5 | Name 1
6 | Name 1
7 | Name 1
8 | Name 1
9 | Name 1
10 | Name 1
1 | Name 2
2 | Name 2
3 | Name 2
4 | Name 2
5 | Name 2
6 | Name 2
7 | Name 2
8 | Name 2
9 | Name 2
10 | Name 2
1 | Name 3
2 | Name 3
3 | Name 3
4 | Name 3
5 | Name 3
6 | Name 3
7 | Name 3
8 | Name 3
9 | Name 3
10 | Name 3
(30 rows)
I'm not really familiar with ireport, but from the PostgreSQL perspective, I believe you're looking for crosstab. Bellow an example:
(If you haven't installed the extension yet, just execute this command)
CREATE EXTENSION tablefunc
Considering the following table (I believe it's close to your structure):
CREATE TEMPORARY TABLE t (id INT, name TEXT,val INT);
And the following values ...
db=#INSERT INTO t VALUES (1,'Name1',10),
(2,'Name1',20),
(3,'Name1',80),
(1,'Name2',30),
(2,'Name2',52),
(3,'Name2',40);
db=# SELECT * FROM t;
id | name | val
----+-------+-----
1 | Name1 | 10
2 | Name1 | 20
3 | Name1 | 80
1 | Name2 | 30
2 | Name2 | 52
3 | Name2 | 40
(6 Zeilen)
... you can use crosstab to display your results horizontally:
db=# SELECT *
FROM crosstab( 'SELECT name,id,val FROM t')
AS j(name text, val1 int, val2 int, val3 int);
name | val1 | val2 | val3
-------+------+------+------
Name1 | 10 | 20 | 80
Name2 | 30 | 52 | 40
(2 Zeilen)

count() corresponding to max() of different values satisfying some condition

I have the following tables:
user_group
usergrp_id bigint Primary Key
usergrp_name text
user
user_id bigint Primary Key
user_name text
user_usergrp_id bigint
user_loc_id bigint
user_usergrp_id has its corresponding id from the user_group table
user_loc_id has its corresponding id(branch_id) from the branch table.
branch
branch_id bigint Primary Key
branch_name text
branch_type smallint
branch_type By default is set as 1. Although it may contain any value in between 1 and 4.
user_projects
proj_id bigint Primary Key
proj_name text
proj_branch_id smallint
proj_branch_id has its corresponding id(branch_id) from the branch table.
user_approval
appr_id bigint Primary Key
appr_prjt_id bigint
appr_status smallint
appr_approval_by bigint
appr_approval_by has its corresponding id(user_id) from the user table
appr_status may contain different status values like 10,20,30... for a single appr_prjt_id
user_group
usergrp_id | usergrp_name
-------------------------
1 | Admin
2 | Manager
user
user_id | user_name | user_usergrp_id |user_loc_id
---------------------------------------------------
1 | John | 1 | 1
2 | Harry | 2 | 1
branch
branch_id | branch_name | branch_type
-------------------------------------
1 | location1 | 2
2 | location2 | 1
3 | location3 | 4
4 | location4 | 2
5 | location4 | 2
user_projects
proj_id | proj_name | proj_branch_id
------------------------------------
1 | test1 | 1
2 | test2 | 2
3 | test3 | 1
4 | test4 | 3
5 | test5 | 1
6 | test5 | 4
user_approval
appr_id | appr_prjt_id | appr_status | appr_approval_by
-------------------------------------------------------
1 | 1 | 10 | 1
2 | 1 | 20 | 1
3 | 1 | 30 | 1
4 | 2 | 10 | 2
5 | 3 | 10 | 1
6 | 3 | 20 | 2
7 | 4 | 10 | 1
8 | 4 | 20 | 1
Condition: The output must take the MAX() value of appr_status for each appr_prjt_id and count it.
I.e., in the above table appr_prjt_id=1 has 3 different status: 10, 20, 30. Its count must only be shown for status corresponding to 30 in the output (not in the statuses 10 and 20), corresponding to a user group in a particular branch_name. Similarly for each of the other id's in the field appr_prjt_id
SQL Fiddle
Desired Output:
10 | 20 | 30
------> Admin 0 | 1 | 1
|
location1
|
------> Manager 1 | 1 | 0
How can I do that?
SQL Fiddle
SQL Fiddle
select
branch_name, usergrp_name,
sum((appr_status = 10)::integer) "10",
sum((appr_status = 20)::integer) "20",
sum((appr_status = 30)::integer) "30"
from
(
select distinct on (appr_prjt_id)
appr_prjt_id, appr_approval_by, appr_status
from user_approval
order by 1, 3 desc
) ua
inner join
users u on ua.appr_approval_by = u.user_id
inner join
user_group ug on u.user_usergrp_id = ug.usergrp_id
inner join
branch b on u.user_loc_id = b.branch_id
group by branch_name, usergrp_name
order by usergrp_name
The classic solution, that works in most DBMSs is to use a case:
select
branch_name, usergrp_name,
sum(case appr_status when 10 then 1 else 0 end) "10",
But Postgresql has the boolean type and it has a cast to integer (boolean::integer) resulting in 0 or 1 which makes for less verbose code.
In this case it is also possible to do a count in instead of a sum:
select
branch_name, usergrp_name,
count(appr_status = 10 or null) "10",
I indeed prefer the count but I have the impression that it is harder to understand. The trick is to know that count counts anything not null and that a (true or null) is true and a (false or null) is null so it will count whenever the condition is true.