How to perform select group by with max in PowerShell? - powershell

I have an object containing the following in PowerShell:
Date Item Total
---- ---- -----
20190505 AAA 2
20190505 BBB 1
20190514 AAA 6
20190514 BBB 1
20190514 CCC 2
20190524 AAA 5
20190524 BBB 1
20190524 CCC 1
20190524 DDD 2
I want to select the maximum total for each type of item. The result should look something like this:
Item Total
---- -----
AAA 6
BBB 1
CCC 2
DDD 2

I found a solution:
$myObject | Group-Object -Property Item | Foreach {
$_.Group | Sort Total -Descending | Select -First 1
}

Related

Postgres GROUP BY an array column

I have a list of students and parents and would like to group them into families using the student id's. Parents who share common student id's can be considered to be a family while also students who share common parent id's can be considered to be a family. This is a sample table:
p_id | parent_name | s_id | student_name |
------------------------------------------|
1 | John Doe | 100 | Mike Doe |
3 | Jane Doe | 100 | Mike Doe |
3 | Jane Doe | 105 | Lisa Doe |
5 | Will Willy | 108 | William Son |
I'd like to end up with something like:
parents | students |
-------------------|------------------------|
John Doe, Jane Doe | Mike Doe, Lisa Doe |
Will Willy | William Son |
To achieve this I'm currently using:
SELECT array_agg(parents) AS parents FROM (
SELECT array_agg(p_id) AS par_ids, array_agg(parent_name) AS parents, student_name, s_id
FROM (
/* sub query */
)b
GROUP BY s_id, student_name
ORDER BY parents ASC
)c
GROUP BY unnest(par_ids)
ORDER BY parents ASC
But I get an error: ERROR: cannot accumulate arrays of different dimensionality. SQL state: 2202E
How can I attain the desired results?
The inner query from the above statement returns:
| par_ids | parents | student_name | s_id |
--------------------------------|------------------------|
| {1,3} | {John Doe, Jane Doe}| Mike Doe | 100 |
| {3} | {Jane Doe} | Lisa Doe | 105 |
| {5} | {Will Willy} | William Son | 108 |
Grouping these students now to the parents is where I'm stuck.
I did something similar (but a bit more complex) already here: https://stackoverflow.com/a/53129510/3984221
step-by-step demo:db<>fiddle
SELECT
array_agg(parent_name) as parents, -- 4
array_agg(student_name) as students
FROM (
SELECT DISTINCT ON (t.s_id) -- 3
*
FROM (
SELECT
s_id,
array_agg(p_id) as parents -- 1
FROM mytable
GROUP BY s_id
) s JOIN mytable t ON t.p_id = ANY(s.parents) -- 2
ORDER BY t.s_id, CARDINALITY(parents) DESC -- 3
) s
GROUP BY parents
Aggregate the p_id values into an array:
s_id
parents
108
{5}
105
{3}
100
{1,3}
Self-join the original table on this array:
s_id
parents
p_id
parent_name
s_id
student_name
100
{1,3}
1
John Doe
100
Mike Doe
105
{3}
3
Jane Doe
100
Mike Doe
100
{1,3}
3
Jane Doe
100
Mike Doe
105
{3}
3
Jane Doe
105
Lisa Doe
100
{1,3}
3
Jane Doe
105
Lisa Doe
108
{5}
5
Will Willy
108
William Son
Remove all duplicate student records. The remaining ones should be the records with the most complete p_id array. This can be done using DISTINCT ON(s_id) on a descending order by the array length:
s_id
parents
p_id
parent_name
s_id
student_name
100
{1,3}
1
John Doe
100
Mike Doe
100
{1,3}
3
Jane Doe
105
Lisa Doe
108
{5}
5
Will Willy
108
William Son
Finally you can group by the p_id array and aggregate the two name columns:
parents
students
{"John Doe","Jane Doe"}
{"Mike Doe","Lisa Doe"}
{"Will Willy"}
{"William Son"}
If you don't want to get an array, but a string list, you can use string_agg(name_colum, ',') instead of array_agg(name_column)

SUM of two level group by in postgresql

I have three table as given below
student
id name stand_id sub_id gender
---------------------------------------
1 | Joe | 1 | 1 | M
2 | Saun | 2 | 1 | F
3 | Paul | 1 | 2 | F
4 | Sena | 2 | 2 | M
Subject
id name
1 Math
2 English
Standard
id name
1 First
2 Second
How can I achieve this kind of multiple group by like standard, subject than total number of boys and girls.
Should I use with, union or union all ?
First
Math
boys total
girls total
second
math
boys total
girls total
It's not completely clear what you are attempting. My interpretation is that you are looking for the total of students by standard, subject and gender.
If that is correct, you need to join together the tables and count the students at the appropriate grain, like so:
SELECT
sta.name AS standard_name,
sub.name AS subject_name,
CASE stu.gender WHEN 'M' THEN 'Boys' ELSE 'Girls' END AS student_gender,
COUNT(stu.id) AS total
FROM
student stu
JOIN
subject sub
ON (stu.sub_id = sub.id)
JOIN
standard sta
ON (stu.stand_id = sta.id)
GROUP BY
standard_name,
subject_name,
student_gender;
Based on your sample data, it would return this:
standard_name | subject_name | student_gender | total
-----------------------------------------------------
First | Math | Boys | 1
First | English | Girls | 1
Second | Math | Girls | 1
Second | English | Boys | 1
Is it what you are looking for
SELECT sd.name,
sj.name,
count(st.gender) filter (
WHERE st.gender='M') AS MALE,
count(st.gender) filter (
WHERE st.gender='F') AS FEMALE
FROM Standard sd
INNER JOIN Student st ON (st.stand_id=sd.id)
INNER JOIN Subject sj ON (sj.id=st.sub_id)
GROUP BY sd.name,
sj.name;
name | name | male | female
--------+---------+------+--------
First | Math | 1 | 0
First | English | 0 | 1
Second | English | 2 | 1
Second | Math | 0 | 1
(4 rows)
I have added some more rows to second English.

T-SQL: Rows to Columns With Count

Let me draw up the table first (there are dozens of columns and dozens of values under Code in reality)
Code | Pat | Col1 | Col2 | Col3
---------------------------------
ABC | 001 | | XX | Q1
ABC | 002 | xx | xx | Q1
ABC | 003 | xx | xxx | Q1
DEF | 004 | xx | xx | Q1
DEF | 005 | xx | xx | Q1
DEF | 006 | xx | xxx | Q1
The resulting table need to look like
ABC | DEF
---------
2 | 3
3 | 3
Let me try and explain. For each 'Code' column, I would need to count the number of entries in Col1 to ColX where the cell is not null/empty.
So in example above, Code ABC has a count of 2 in Col1 and a count of 3 in Col2 Similarly for DEF, both have a count of 3
I've tried lots of things but got to the point where I'm now looking at a blank page again!
ALTERNATIVELY
Code | Col1 | Col2
--------------------
ABC | 2 | 3
DEF | 3 | 3
Please advise
The alternative solution can be reached by using GROUP BY and summing up a calculated number:
SELECT
[Code],
SUM(CASE WHEN ISNULL(Col1, '') = '' THEN 0 ELSE 1 END) as [Col1],
SUM(CASE WHEN ISNULL(Col2, '') = '' THEN 0 ELSE 1 END) as [Col2],
...
FROM T
GROUP by [Code]

update one column based on other column value

I have a table where if same name comes it should have same id if not then I need to update the Id column with lowest id number if the name is same.
My data looks like this
Name | Id
AAA | 1
AAA | 2
BBB | 4
BBB | 4
BBB | 5
the output should be
Name | Id
AAA | 1
AAA | 1
BBB | 4
BBB | 4
BBB | 4
You can use OLAP functions for that.
http://www-01.ibm.com/support/knowledgecenter/SSEPGG_10.5.0/com.ibm.db2.luw.sql.ref.doc/doc/r0023461.html

How to select data with multiple row output from 1 row (PostgreSQL)

I have data on table test like this
customer_no | name | chance
---------------------------
00000000001 | AAAA | 3
00000000002 | BBBB | 2
00000000003 | CCCC | 1
Now,i want to select from table test with multiple output that calculate by value of field chance
output like this
customer_no | name
------------------
00000000001 | AAAA
00000000001 | AAAA
00000000001 | AAAA
00000000002 | BBBB
00000000002 | BBBB
00000000003 | CCCC
how to select command in pgsql database?
Try this:
SELECT customer_no, name FROM (
SELECT test.*,
generate_series(1,chance) i
FROM test
) test;
Here is a demo.
with recursive CTE_nums as (
select max(chance) as num from test
union all
select num - 1 from CTE_nums
where num > 1
)
select
t.customer_no, t.name
from test as t
inner join CTE_nums as n on n.num <= t.chance
order by 1, 2
SQL FIDDLE EXAMPLE