How to get MAX rownumber with rowNumber in same query - sql

I have ROW_NUMBER() OVER (ORDER BY NULL) rnum in a sql statement to give me row numbers. is there a way to attach the max rnum to the same dataset going out?
what I want is the row_number() which I get, but I also want the MAXIMUM rownumber of the total return on each record.
SELECT
ROW_NUMBER() OVER (ORDER BY NULL) rnum,
C.ID, C.FIELD1, C."NAME", C.FIELD2, C.FIELD3
FROM SCHEMA.TABLE
WHERE (C.IS_CRNT = 1)
), MAX_NUM as (
SELECT DATA.ID, max(rnum) as maxrnum from DATA GROUP BY DATA.COMPONENT_ID
) select maxrnum, DATA.* from DATA JOIN MAX_NUM on DATA.COMPONENT_ID = MAX_NUM.COMPONENT_ID
DESIRED RESULT (ASSUMING 15 records):
1 15 DATA
2 15 DATA
3 15 DATA
etc...

I think you want count(*) as a window function:
SELECT ROW_NUMBER() OVER (ORDER BY NULL) as rnum,
COUNT(*) OVER () as cnt,
C.ID, C.FIELD1, C."NAME", C.FIELD2, C.FIELD3
FROM SCHEMA.TABLE
WHERE C.IS_CRNT = 1

Based on my assumptions in your dataset, this is the approach I would take:
WITH CTE AS (
select C.ID, C.FIELD1, C."NAME", C.FIELD2, C.FIELD3, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID)
FROM SCHEMA.TABLE WHERE (C.IS_CRNT = 1))
SELECT *, (select count(*) from cte) "count" from cte;

Related

Selecting records that appear several times in a row

My problem is that I would like to select some records which appears in a row.
For example we have table like this:
x
x
x
y
y
x
x
y
Query should give answer like this:
x 3
y 2
x 2
y 1
SQL tables represent unordered sets. Your question only makes sense if there is a column that specifies the ordering. If so, you can use the difference-of-row-numbers to determine the groups and then aggregate:
select col1, count(*)
from (select t.*,
row_number() over (order by <ordering col>) as seqnum,
row_number() over (partition by col1 order by <ordering col>) as seqnum_2
from t
) t
group by col1, (seqnum - seqnum_2)
I made a SQL Fiddle
http://sqlfiddle.com/#!18/f8900/5
CREATE TABLE [dbo].[SomeTable](
[data] [nchar](1) NULL,
[id] [int] IDENTITY(1,1) NOT NULL
);
INSERT INTO SomeTable
([data])
VALUES
('x'),
('x'),
('x'),
('y'),
('y'),
('x'),
('x'),
('y')
;
select * from SomeTable;
WITH SomeTable_CTE (Data, total, BaseId, NextId)
AS
(
SELECT
Data,
1 as total,
Id as BaseId,
Id+1 as NextId
FROM SomeTable
where not exists(
Select * from SomeTable Previous
where Previous.Id+1 = SomeTable.Id
and Previous.Data = SomeTable.Data)
UNION ALL
select SomeTable_CTE.Data, SomeTable_CTE.total+1, SomeTable_CTE.BaseId as BaseId, SomeTable.Id+1 as NextId
from SomeTable_CTE inner join SomeTable on
SomeTable.Data = SomeTable_CTE.Data
and
SomeTable.Id = SomeTable_CTE.NextId
)
SELECT Data, max(total) as total
FROM SomeTable_CTE
group by Data, BaseId
order by BaseId
The elephant in the room is the missing column(s) to establish the order of rows.
SELECT col1, count(*)
FROM (
SELECT col1, order_column
, row_number() OVER (ORDER BY order_column)
- row_number() OVER (PARTITION BY col1 ORDER BY order_column) AS grp
FROM tbl
) t
GROUP BY col1, grp
ORDER BY min(order_column);
To exclude partitions with only a single row, add a HAVING clause:
SELECT col1, count(*)
FROM (
SELECT col1, order_column
, row_number() OVER (ORDER BY order_column)
- row_number() OVER (PARTITION BY col1 ORDER BY order_column) AS grp
FROM tbl
) t
GROUP BY col1, grp
HAVING count(*) > 1
ORDER BY min(order_column);
db<>fiddle here
Add a final ORDER BY to maintain original order (and a meaningful result). You may want to add a column like min(order_column) as well.
Related:
Find the longest streak of perfect scores per player
Select longest continuous sequence
Group by repeating attribute

Random allocation of records between two tables

I want to assign the values from Table B to Table A, but so that each record in Table B occurs in the same number of repetitions.
Fiddle SQL
You can use window functions for this and mod arithmetic. For simple repetition:
with a as (
select a.*, rownum as seqnum
from a
),
b as (
select b.*, rownum as seqnum, count(*) over () as cnt
from b
)
select a.col, b.col
from a join
b
on mod(a.seqnum - 1, b.cnt) = b.seqnum - 1;
For more random assignment, randomize the seqnums:
with a as (
select a.*,
row_number() over (order by dbms_random.random) as seqnum
from a
order by db
),
b as (
select b.*, count(*) over () as cnt,
row_number() over (order by dbms_random.random) as seqnum
from b
)
select a.col, b.col
from a join
b
on mod(a.seqnum - 1, b.cnt) = b.seqnum - 1;
You can use the ROWNUM for achieving the same:
SELECT
COLOUR,
EMP
FROM
(
SELECT
COLOUR,
ROWNUM RN
FROM
T1
) T1,
(
SELECT
EMP,
ROWNUM RN
FROM
T2
) T2
WHERE
MOD(T1.RN, 2) + 1 = T2.RN
Fiddler SQL QUERY
Try this,
with Employees as
(select Emp, Row_Number() Over(order by 1) Rn
from B
cross join (select 1
from Dual
connect by level < (select count(1)
from A) / (select count(1)
from B) + 1)
order by Dbms_Random.Value),
Colours as
(select Colour, Rownum Rn
from A)
select t.Colour, k.Emp
from Colours t
join Employees k
on t.Rn = k.Rn

Trouble using ROW_NUMBER() OVER (PARTITION BY

I have this query :
SELECT
Reservation.*,
ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY (SELECT NULL)) AS RowNums
FROM
Reservation
WHERE
RowNums = 1
I get this error :
Msg 207, Level 16, State 1, Line 2
Invalid column name 'RowNums'.
I don't know where the problem is - any help?
You'd need to use a CTE:
WITH tempData AS
(
SELECT Reservation.*,
ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY (SELECT NULL)) AS RowNums
FROM Reservation
)
SELECT * FROM tempData WHERE RowNums = 1
However, a cleaner approach would be to use WITH TIES:
SELECT TOP 1 WITH TIES *
FROM Reservation
ORDER BY ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY (SELECT NULL))
You can't use RowNums directly,
Try like this,
SELECT *
FROM
(
SELECT Reservation.*,ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY (SELECT NULL)) AS RowNums
FROM Reservation
) S
where RowNums = 1
SELECT t.*
FROM
(SELECT Reservation.*,ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY NULL ) AS RowNums
FROM Reservation) t
where RowNums = 1
You cannot use this directly as this is not a column in the table. Either use CTE or derived table.
CTE
:WITH C AS (
SELECT Reservation.*,ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY (SELECT NULL)) AS RowNums
)
SELECT * FROM C WHERE RowNums = 1
Try this
;WITH CTE AS(
SELECT Reservation.*,
ROW_NUMBER() OVER (PARTITION BY code_bien ORDER BY (SELECT NULL)) AS RowNums
FROM Reservation)
SELECT * FROM CTE
WHERE RowNums = 1

SQL Server ROW_NUMBER() Issue

I'm using row_number() expression but I don't get result as I expected. I have a sql table and some rows are duplicate. They have same 'BATCHID' and I want to get second row number for these, for others I use first row number. How can I do it?
SELECT * FROM (SELECT * , ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY) Rn FROM SAYIMDCPC ) t
WHERE Rn=1
This code returns to me only first rows, but I want to get second rows for duplicated items.
ROW_NUMBER() gives every row a unique counter. You'd want to use RANK(), which is similar, but gives rows with identical values the same score:
SELECT *
FROM (SELECT * , RANK() OVER (PARTITION BY batchid ORDER BY scaqry) rk
FROM sayimdcpc) t
WHERE rk = 1
If some values are only shown once, but some twice (and perhaps more than twice), you don't want the "first" row, you want the "max" row. Try reversing your order condition:
SELECT *
FROM (SELECT * ,
ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY DESC) Rn
FROM SAYIMDCPC ) t
WHERE Rn=1
As a side note, it's still better to explicitly list out all columns; for instance, you probably don't need Rn outside of this query...
Simply try this,
SELECT * FROM (SELECT * , ROW_NUMBER() OVER (ORDER BY SCAQTY) Rn FROM SAYIMDCPC ) t
WHERE Rn=1
To rephrase it another way, it sounds like you're saying, "When there's a single row for the Batch ID, return the single row. When there are 2 or more rows, return the second row." That's going to require inspecting your Rn value to see what its max is. I don't think you can do it in a single query.
So I'd try something like this:
WITH NumberedRows AS (
SELECT * ,
ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY) Rn
FROM SAYIMDCPC
)
, MaxNumber AS (
SELECT Max(RN) as MaxRn,
BATCHID
FROM NumberedRows
GROUP BY BATCHID
)
, NonDupes AS (
SELECT *
FROM NumberedRows
WHERE BATCHID NOT IN (SELECT BATCHID FROM MaxNumber WHERE MaxNumber = 1)
)
, SecondRows AS (
SELECT (
FROM NumberedRows
WHERE BATCHID NOT IN (SELECT BATCHID FROM MaxNumber WHERE MaxNumber > 1)
AND Rn = 2
)
SELECT
FROM NonDupes
UNION ALL
SELECT *
FROM SecondRows
Please try this. It will select max row num, if no duplicate then it should be first one otherwise second
select * from (SELECT * , ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY) Rn FROM SAYIMDCPC ) d,
(SELECT batchid,max(Rn) maxRn FROM (SELECT * , ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY) Rn FROM SAYIMDCPC ) t
group by batchid) q
where d.batchid = q.batchid and d.rn = q.maxrn
correct me if i am wrong
e.g sample data
BatchID, SCAQTY
1 , 10
2 , 10
2 , 20
2 , 30
is your expectation result like below?
**Expectation Result 1**
BatchID , SCAQty
1 , 10
2 , 30
or
**Expectation Result 2**
BatchID , SCAQty
1 , 10
2 , 20
2 , 30
based on my understanding what you want to perform is Expectation Result 1, so i guess Query below should able to help u, you just need to add desc for SCAQTY in your query
SELECT * FROM (SELECT * ,
ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY DESC) Rn FROM SAYIMDCPC ) t
WHERE Rn=1
Total result set with duplicates and non duplicates. The first column "IsDuplicate" indicates if the column is a duplicate or not.
;WITH d1 AS (
SELECT Seq = ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY)
,*
FROM SAYIMDCPC
)
SELECT IsDuplicate = CONVERT(BIT, Seq)
,*
FROM d1
This will give you only the duplicates:
;WITH d1 AS (
SELECT Seq = ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY)
,*
FROM SAYIMDCPC
)
SELECT IsDuplicate = CONVERT(BIT, Seq)
,*
FROM d1
WHERE Seq > 1
This will give you only the non duplicates (as in your first query)
;WITH d1 AS (
SELECT Seq = ROW_NUMBER() OVER (PARTITION BY BATCHID ORDER BY SCAQTY)
,*
FROM SAYIMDCPC
)
SELECT IsDuplicate = CONVERT(BIT, Seq)
,*
FROM d1
WHERE Seq = 1

How do I create a temp table using this snippet?

how do i produce this SQL snippet as a temp table so I can join some other stuff into it?
with MyCTE AS
(
select *, RANK() OVER (PARTITION BY workplace ORDER BY Total DESC) AS Rank
from [dbo].[OriginDestination]
)
select * from MyCTE where Rank <= 5
Like this:
with MyCTE AS
(
select *, RANK() OVER (PARTITION BY workplace ORDER BY Total DESC) AS Rank
from [dbo].[OriginDestination]
)
select *
into #yourTempTable
from MyCTE
where Rank <= 5