max(count) from inner query using row_number() - sql

I am trying to pick the src_cd which has the maximum count in my inner query:
select count(*), src_cd
from innertable1
group by src_cd
Result for the above query is:
cnt
src_cd
100
CCC
90
BBB
80
AAA
From the above result I want to do a
select *
from table1
where src_cd having max(cnt of src_cd from innertable1)
I also want to use row_number() to pick the 2nd max, 3rd max and so on

You can use limit 1 with order by to pick largest.
select count(*), src_cd
from innertable1
group by src_cd
order by 1 desc
limit 1
Order by will order in descending order of count.
limit will pick up first row.
You can also use subquery to calculate next max rows using row_number().
select src_cd as second_max
from (
select src_cd, row_number() over( order by cnt desc) as rownum
from (
select count(*) cnt, src_cd
from innertable1
group by src_cd
)rs
) rs2
where rownum=2 -- second MAX

Related

How to find Min and Max rows from a table including all columns from postgresql

I have a view select c1,c2,count from table and it will give result below.
I want to fetch the entire row of maximum and minimum count's value and that should return only two rows with max and min count like below.
How to do it?
The quickest way is probably a union:
(
select c1, c2, count
from the_table
order by count
limit 1
)
union all
(
select c1, c2, count
from the_table
order by count desc
limit 1
)
Usually the individual statements in a UNION, don't need parentheses, but as we want an order by on each of them, they are needed.
Another option would be join against a derived table:
select t1.*
from the_table t1
join (
select min(count) as min_count,
max(count) as max_count
from the_table
) mm on t1.count in (mm.min_count, mm.max_count)
But I doubt that this will be faster.
I would recommend window functions:
select *
from (
select t.*,
row_number() over(order by count) rn_asc,
row_number() over(order by count desc) rn_desc
from mytable t
) t
where 1 in (rn_asc, rn_desc)
order by count
This requires scanning the table only once (as opposed to union all or join).

sql: Select count(*) - nth record from each group

I'm grouping by tenant_id. I want to select the count() - 1000th record (ordered by _updated time) from each GROUPBY group, for the groups where count() is greater than 1000. As follows:
select t1.tenant_id,
(select temp._updated
from trace temp
where temp.tenant_id = t1.tenant_id
order by _updated limit 1 offset
count(*) - 1000
) as timekey
from fgc.trace as t1
group by tenant_id
having count(*) > 1000;
But this is not allowed as count(*) cannot be used inside the subquery.
So I tried the following, which still doesn't work as I don't have access to t1 since this is not a join.
select t1.tenant_id,
(select temp._updated
from trace temp
where temp.tenant_id = t1.tenant_id
order by _updated limit 1 offset
(select count(*)-1000
from trace t2
group by tenant_id
having t2.tenant_id = t1.tenant_id)
) as timekey
from fgc.trace as t1
group by tenant_id
having count(*) > 1000;
So how can I get the following?
tenant_id | timekey
+-----------+----------------------------------+
n7ia6ryc | 2019-07-23 23:09:49.951406+00:00
You seem to want ROW_NUMBER(). Cockroach supports windows functions, so:
SELECT updated
FROM (
SELECT
tenant_id,
updated,
ROW_NUMBER() OVER(PARTITION BY tenant_id ORDER BY updated DESC) rn
FROM trace
) x WHERE rn = 1001
For each tenant_id, this will return the timestamp of the 1001th less recent record. If a given tenant has less than 1000 records, it will not appear in the results.
select x.tenant_id
from (
select t.tenant_id,
row_number() over (partition by t.tenant_id order by t.timekey) as tenant_number
from fgc.trace as t
) x
where x.tenant_number > 1000
group by x.tenant_id
just the one timestamp would look like this:
select min(x.timekey) as min_timestamp
from (
select t.tenant_id, t.timekey,
row_number() over (partition by t.tenant_id order by t.timekey) as tenant_number
from fgc.trace as t
) x
where x.tenant_number > 1000
note that grouping does not matter here because each row can only be in one group and you are only looking at one row.

How to find most frequent value in SQL column and return that value?

I was trying to do something like this:
select nume_produs
from incasari
group by id
having count(nume_produs) = max(count(nume_produs));
but it doesn't work
Do a GROUP BY. Order by count descending. Fetch the first row (highest count) only.
select nume_produs, count(*) as cnt
from incasari
group by nume_produs
order by cnt desc
fetch first 1 row with ties
For the most common value in the column:
select num_produs
from (select nume_produs, count(*) as cnt,
row_number() over (order by count(*)) as seqnum
from incasari
group by nume_produs
) i
where seqnum = 1;
If you want multiple values in the event of duplicates, use rank() instead of row_number().
If you want the most common value per id, then add partition by:
select num_produs
from (select nume_produs, count(*) as cnt,
row_number() over (partition by id order by count(*)) as seqnum
from incasari
group by nume_produs
) i
where seqnum = 1;
SELECT `nume_produs`,
COUNT(`nume_produs`) AS `value_occurrence`
FROM `incasari`
GROUP BY `nume_produs`
ORDER BY `value_occurrence` DESC
LIMIT 1;
Increase 1 if you want to see the N most common values of the column.

Faster select Max SQL Query

Here is the query to select the Config Type that has the Max number of rows.
Is there another way that is just as fast as the second query to select the data?
select CONFIG_TYPE, MAX(COUNTING) FROM
(select CONFIG_TYPE, COUNT(*) as COUNTING FROM NOTIFICATION_CONFIG GROUP BY CONFIG_TYPE)
WHERE COUNTING =
(select MAX(COUNTING) FROM
(select COUNT(*) as COUNTING FROM NOTIFICATION_CONFIG GROUP BY CONFIG_TYPE)
)GROUP BY CONFIG_TYPE
This second query will do the job in 1 search, unlike the other that does it in 2.
select CONFIG_TYPE, COUNTING FROM
(select CONFIG_TYPE, COUNT(*) as COUNTING FROM NOTIFICATION_CONFIG
GROUP BY CONFIG_TYPE ORDER BY COUNTING DESC FETCH FIRST 1 ROW ONLY)
just wondering if there was another way to do this.
Use window functions!
SELECT c.*
FROM (SELECT CONFIG_TYPE, COUNT(*) as COUNTING,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM NOTIFICATION_CONFIG
GROUP BY CONFIG_TYPE
) c
WHERE seqnum = 1;
This uses RANK(), so it will return all maximum values (in the case of ties). If you want one arbitrary maximum returned in the case of ties, then use ROW_NUMBER() instead. Or, if you don't want ties, you can do:
SELECT CONFIG_TYPE, COUNT(*) as COUNTING
FROM NOTIFICATION_CONFIG
GROUP BY CONFIG_TYPE
ORDER BY COUNT(*) DESC
FETCH FIRST 1 ROW ONLY;
this is just messed up
select CONFIG_TYPE, MAX(COUNTING)
FROM ( select CONFIG_TYPE, COUNT(*) as COUNTING
FROM NOTIFICATION_CONFIG
GROUP BY CONFIG_TYPE
)
WHERE COUNTING = ( select MAX(COUNTING)
FROM ( select COUNT(*) as COUNTING
FROM NOTIFICATION_CONFIG
GROUP BY CONFIG_TYPE
)
)
GROUP BY CONFIG_TYPE

Need to change LIMIT into something else

Is there a way to change "LIMIT 1" and get the same output? I have to get client's name, surname and a quantity of books that has the most books
SELECT stud.skaitytojas.name, stud.skaitytojas.surname,
COUNT (stud.skaitytojas.nr) AS quantity
FROM stud.egzempliorius , stud.skaitytojas
WHERE stud.egzempliorius.client = stud.skaitytojas.nr
GROUP BY stud.skaitytojas.nr
ORDER BY quantity DESC
LIMIT 1
Postgres supports the ANSI standard FETCH FIRST 1 ROW ONLY, so you can do:
SELECT s.name, s.surname, COUNT(s.nr) AS quantity
FROM stud.egzempliorius e JOIN
stud.skaitytojas s
ON e.client = s.nr
GROUP BY s.name, s.surname
ORDER BY quantity DESC
FETCH FIRST 1 ROW ONLY;
Also notice the use of table aliases and proper JOIN syntax. I also prefer to list the columns in the SELECT in the GROUP BY, although that is optional if s.nr is unique.
You can select the row with the highest quantity using row_number()
SELECT * FROM (
SELECT * , row_number() over (order by quantity desc) rn FROM (
SELECT stud.skaitytojas.name, stud.skaitytojas.surname, COUNT (stud.skaitytojas.nr) AS quantity
FROM stud.egzempliorius , stud.skaitytojas
WHERE stud.egzempliorius.client = stud.skaitytojas.nr
GROUP BY stud.skaitytojas.name, stud.skaitytojas.surname
) t
) t where rn = 1
If you want to include ties for the highest quantity, then use rank() instead.