I want to generate continuously number by 2 column and batch wise - sql

I want to generate continuously number with the combination of 2 columns and in batch size of 5. Anybody can help to solve this?

An adoption of #GordonLinoff's answer...
SELECT
name,
rank,
DENSE_RANK() OVER (ORDER BY name DESC, Rank, ((seqnum - 1) / 5)) AS rno
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY name, rank ORDER BY (SELECT null)) AS seqnum
FROM
yourTable
)
sequenced
ORDER BY
3

You can use row_number() and arithmetic:
select name, rank,
((seqnum - 1) / 5) + 1 as rno
from (select t.*,
row_number() as (partition by name, rank order by (select null)) as seqnum
from t
) t
order by seqnum;

Related

Finding Median Using MySQL

I know that there are many ways to find the median, but I am trying to use this method to find the median. Can someone explain to me why this does not work? The error here says "Invalid use of group function," but when I use HAVING instead of WHERE, the system doesn't recognize what RowNumber is. I'm very confused.
SELECT
ROUND(AVG(LS.LAT_N))
FROM(
SELECT
LAT_N,
ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowNumber
FROM
STATION
) AS LS
WHERE
RowNumber IN (
IF(
FLOOR(COUNT(LS.LAT_N)/2+0.5) = CEIL(COUNT(LS.LAT_N)/2+0.5),
FLOOR(COUNT(LS.LAT_N)/2+0.5),
FLOOR(COUNT(LS.LAT_N)/2+0.5) AND CEIL(COUNT(LS.LAT_N)/2+0.5)
)
I typically write this as:
SELECT AVG(LAT_N)
FROM (SELECT LAT_N,
ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowNumber,
COUNT(*) OVER () as cnt
FROM STATION
) s
WHERE 2 * RowNumber IN (CNT, CNT + 1, CNT + 2);
Here is a db<>fiddle.
The median is the middle element in an ordered series - or the average of the two middle elements if there is an even number.
SELECT
AVG(LAT_N)
FROM(
SELECT
LAT_N,
ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowNumber
FROM
STATION
) AS q
WHERE
RowNumber >= FLOOR ( (SELECT COUNT(*) FROM STATION)/2 + 0.5)
AND
RowNumber <= CEIL ( (SELECT COUNT(*) FROM STATION)/2 + 0.5)
Here is dbfiddle https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=b31e08f4ece61ecb95d9dde76c389fb1

Max and Min row numbers from single cte code block

;with cte1 as
( select id,
row_number() over (partition by pk,pp,sn order by id asc)
as rn
from mqms_production
) select * into #M from cte1 where rn=1
With the above, I get all the rows with rn=1 but I also want to copy to another table all the rows with max rn for a given partition pk,pp, sn.
Is it possibleto do it without having to write the cte block again with
(partition by pk,pp,sn order by id DESC)
thanks!
You can just add another window function based expression there with reverse sort order and get the top rows on both of them
with cte1 as (
select id,
row_number() over (partition by pk,pp,sn order by id asc) as rn1,
row_number() over (partition by pk,pp,sn order by id desc) as rn2
from mqms_production
)
select * from cte1
where rn1 = 1 or rn2 = 1;

Select only 20 rows of every distinct name

I have a table in which I have over 1000+ rows, in which there is a column "AnaId", values of this column are repeated many times like name 003912 is repeated 85 times, name 003156 in repeated 70 time, I want to select maximum 20 rows of every distinct AnaID. I have no idea how to do it.
SELECT dbo.Analysis.AnaId, Analysis.CasNo, MoleculeId,
SUM(dbo.AnalysisSummary.Area) as TotalArea
FROM dbo.Analysis LEFT JOIN dbo.AnalysisSummary
ON dbo.AnalysisSummary.AnaId = dbo.Analysis.AnaId
WHERE dbo.Analysis.Sample like '%Oil%'
GROUP BY dbo.Analysis.AnaId,Analysis.CasNo, MoleculeId ORDER BY
TotalArea DESC
You can use row_number():
select t.*
from (select t.*, row_number() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
With the edits to your question, you can do:
with t as (
<your query here without order by>
)
select t.*
from (select t.*, row_number() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
If you have another table of names, you can also use cross apply:
select t.*
from names n cross apply
(select top 20 t.*
from t
where t.name = n.name
) t;
Using Rank()
select t.*
from (select t.*, rank() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
Using Dense_Rank()
select t.*
from (select t.*, Dense_Rank() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
Using Row_Number
select t.*
from (select t.*, row_number() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
This will help uunderstand usage of each Special Functions
Base Code Credits:-#gordon

Ranking Over Row_Number in SQL

I am posting a sample data below.
What I have is a row number which generated a number based on Date and Name columns (achieved using ROW_NUMBER function). What I need now, is another derived column called Group_Num which creates a number for each group (3 in this case). Can this be achieved considering the fact that my Name column repeats but the Date column value changes?
Thanks in advance.
Check This.
We can achive this using Row_number() ,lag() and SUM() .
select
Date,
Name,
Row_number()over( partition by Group_Num order by ROwiD ) Row_Num,
Group_Num
from
(
SELECT * ,
SUM(R) OVER(ORDER BY RowID) Group_Num
FROM
(
select *,
Case When
lag(name ) OVER (ORDER BY RowID ) = name
then 0 else 1 end as R
from
(
select DATE,NAME,
row_number() OVER ( ORDER BY (select 1)) AS 'RowID'
from #TableName
)A
)B
)C
order by ROwiD
OutPut :
You can use DENSE_RANK:
SELECT Date
, Name
, ROW_NUMBER() OVER(Partition By Name Order By Name, Date) as Row_Num
, DENSE_RANK() Over(order by Name) as Group_Num
FROM #Table

How to group numbered rows into groups

In Sql Server I need to take repeating sets of row numbers and group those into segments or sub groups. I'm trying to achieve column B using Sql. I've achieved column a using the row_number() function but I'm not sure how to get to Column B.
Here is the logic for row_number()
1 + ((row_number() over (order by TimeStamp, FileName, OrderID) - 1) % 5) AS [Row_Number]
Your row_number() is of the form:
row_number() over (partition by colA order by colB)
What you seem to want is:
dense_rank() over (order by colA)
That is, the partition key(s) used for the row_number() should be the order by keys for the dense_rank().
EDIT:
Your code is:
1 + ((row_number() over (order by TimeStamp, FileName, OrderID) - 1) % 5) AS [Row_Number]
In this case, there is no partition by. What you really want simply integer division. This is easy:
1 + ((row_number() over (order by TimeStamp, FileName, OrderID) - 1) / 5) AS [Row_Number]
I would go with a simple solution:
SELECT [Row_Number], GroupNumber
FROM (
SELECT [Row_Number]
, row_number()over(partition by [Row_Number] order by [Row_Number]) as GroupNumber
--Note: The order by clause above should be replaced with however you are ordering the groups of row numbers)
FROM YourTableOrInlineView
) z
ORDER BY GroupNumber, [Row_Number]