find set of values that have max occurrence in column in postgresql - postgresql

Print the name(s) and sid(s) of the student(s) enrolled in the most classes
Enroll
sid class number
1 23
2 54
1 54
3 43
1 43
2 43
student
sid sname
1 sagar
2 kiran
3 ravi
4 vishal
output
sid sname
1 sagar

Group enrollments by students, order by count and use limit 1:
select s.id, s.name
from student s
join enroll e on e.sid = s.id
group by s.id, s.name
order by count(*) desc
limit 1
Note how you don't need the select count(*) - you may simply refer to it.

I think this will help you
SELECT <column_name> FROM <table_name> WHERE <column_name>=
(SELECT <column_name>
FROM (SELECT <column_name>, count(*) as cnt FROM <table_name> GROUP BY <column_name>) AS foo
WHERE foo.cnt=(SELECT MAX(c) FROM (SELECT <column_name>,count(*) AS c FROM <column_name> GROUP BY <column_name>) AS bar)) limit 1

Related

Postgresql group by relation

I want to group the records by relation.
products table:
id
price
1
100
2
200
3
300
4
400
product_properties table:
id
productId
propertyId
1
1
2
2
1
3
3
2
2
4
2
3
5
3
4
6
4
4
The query should select lowest price group by product_properties. I mean, If products have same properties in product_properties, query should return product that has lowest price.
So, For these tables query should return products that have ids 1,3.
I use TypeORM, I tried join the relation and distinct on relation alias name but its not worked.
How can I achieve this?
I wrote two variants query for you:
-- variant 1
select distinct t1.product_id from (
select
pr.price, pp.product_id, pp.property_id, min(pr.price) OVER(PARTITION BY pp.property_id) as min_price
from
test.product_properties pp
inner join
test.products pr on pp.product_id = pr.id
) t1
where
t1.price = t1.min_price;
-- variant 2
select distinct t1.product_id from test.product_properties t1
inner join test.products t2 on t1.product_id = t2.id
inner join (
select
pp.property_id, min(pr.price) as min_price
from
test.product_properties pp
inner join
test.products pr on pp.product_id = pr.id
group by pp.property_id
) t3 on t3.property_id = t1.property_id and t3.min_price = t2.price;

can you helpe me to display the latest data on each group

I have this datatables:
table1
id category
-------------
1 a
2 b
3 c
table2
id heading category_id
----------------------
1 name 1
2 adddress 2
3 phone 3
4 email 1
I want to group this table and display the latest data for that the following query was I used:
SELECT news.id,news.image,news.heading,news.description,
news.date,news.category_id,categories.category
FROM `news`
INNER JOIN categories On news.category_id=categories.id
group by category_id
But I didnt get the latest data that I entered.
Try the query below:
SELECT *
FROM table2 AS tb2 LEFT JOIN table1 AS tb1 ON tb2.category_id = tb1.id
ORDER BY tb1.id
GROUP BY tb2.category_id

Subsetting records that contain multiple values in one column

In my postgres table, I have two columns of interest: id and name - my goal is to only keep records where id has more than one value in name. In other words, would like to keep all records of ids that have multiple values and where at least one of those values is B
UPDATE: I have tried adding WHERE EXISTS to the queries below but this does not work
The sample data would look like this:
> test
id name
1 1 A
2 2 A
3 3 A
4 4 A
5 5 A
6 6 A
7 7 A
8 2 B
9 1 B
10 2 B
and the output would look like this:
> output
id name
1 1 A
2 2 A
8 2 B
9 1 B
10 2 B
How would one write a query to select only these kinds records?
Based on your description you would seem to want:
select id, name
from (select t.*, min(name) over (partition by id) as min_name,
max(name) over (partition by id) as max_name
from t
) t
where min_name < max_name;
This can be done using EXISTS:
select id, name
from test t1
where exists (select *
from test t2
where t1.id = t2.id
and t1.name <> t2.name) -- this will select those with multiple names for the id
and exists (select *
from test t3
where t1.id = t3.id
and t3.name = 'B') -- this will select those with at least one b for that id
Those records where for their id more than one name shines up, right?
This could be formulated in "SQL" as follows:
select * from table t1
where id in (
select id
from table t2
group by id
having count(name) > 1)

Postgres how to maintain order of rows using CTEs

I have 2 tables
students:
id | name | age
1 abc 20
2 xyz 21
scores:
id | studentid | marks
1 1 20
2 2 22
3 2 20
4 1 22
5 1 20
where studentid is foreign key to students table
When a do
select studentid
from scores
where marks=20;
I get the following result
1, 2, 1
But if want the name of the student name and when I do a join using
select t1.name
from students t1
inner join scores t2 on t1.id = t2.studentid
where t2.marks=20;
I get xyz,abc,abc Though the ouput is correct is there any way I can maintain the order in which scores are listed in the scores table? I should get abc,xyz,abc as output. I tried using subquery as well
SELECT name
FROM students
WHERE ID IN ( select studentid from scores where marks=20) ;
but that also did not give me correct order. How can this be achieved using CTEs (common table expressions)? I tried the follownig cte but it did not work
with cte as(
select t2.id, t1.name
from students t1
inner join scores t2 on t1.id = t2.studentid
where t2.marks=20)
select name from cte order by id
You can order by a column not present in select list:
select t1.name
from students t1
inner join scores t2 on t1.id = t2.student_id
where t2.marks=20
order by t2.id;
name
------
abc
xyz
abc
(3 rows)

DB2 query group by id but with max of date and max of sequence

My table is like
ID FName LName Date(mm/dd/yy) Sequence Value
101 A B 1/10/2010 1 10
101 A B 1/10/2010 2 20
101 X Y 1/2/2010 1 15
101 Z X 1/3/2010 5 10
102 A B 1/10/2010 2 10
102 X Y 1/2/2010 1 15
102 Z X 1/3/2010 5 10
I need a query that should return 2 records
101 A B 1/10/2010 2 20
102 A B 1/10/2010 2 10
that is max of date and max of sequence group by id.
Could anyone assist on this.
-----------------------
-- get me my rows...
-----------------------
select * from myTable t
-----------------------
-- limiting them...
-----------------------
inner join
----------------------------------
-- ...by joining to a subselection
----------------------------------
(select m.id, m.date, max(m.sequence) as max_seq from myTable m inner join
----------------------------------------------------
-- first group on id and date to get max-date-per-id
----------------------------------------------------
(select id, max(date) as date from myTable group by id) y
on m.id = y.id and m.date = y.date
group by id) x
on t.id = x.id
and t.sequence = x.max_seq
Would be a simple solution, which does not take account of ties, nor of rows where sequence is NULL.
EDIT: I've added an extra group to first select max-date-per-id, and then join on this to get max-sequence-per-max-date-per-id before joining to the main table to get all columns.
I have considered your table name as employee..
check the below thing helped you.
select * from employee emp1
join (select Id, max(Date) as dat, max(sequence) as seq from employee group by id) emp2
on emp1.id = emp2.id and emp1.sequence = emp2.seq and emp1.date = emp2.dat
I'm a fan of using the WITH clause in SELECT statements to organize the different steps. I find that it makes the code easier to read.
WITH max_date(max_date)
AS (
SELECT MAX(Date)
FROM my_table
),
max_seq(max_seq)
AS (
SELECT MAX(Sequence)
FROM my_table
WHERE Date = (SELECT md.max_date FROM max_date md)
)
SELECT *
FROM my_table
WHERE Date = (SELECT md.max_date FROM max_date md)
AND Sequence = (SELECT ms.max_seq FROM max_seq ms);
You should be able to optimize this further as needed.