Frage

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.

War es hilfreich?

Lösung

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

Andere Tipps

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top