В SQL ранг() в зависимости от числа строк ()
Я запутался в различиях между ними. Выполнив следующий SQL возвращает меня два комплекта идентичный результат. Может кто-нибудь объяснить разницу?
SELECT ID, [Description], RANK() OVER(PARTITION BY StyleID ORDER BY ID) as 'Rank' FROM SubStyle
SELECT ID, [Description], ROW_NUMBER() OVER(PARTITION BY StyleID ORDER BY ID) as 'RowNumber' FROM SubStyle
7 ответов:
функции row_number : возвращает уникальное число для каждой строки, начиная с 1. Для строк, имеющих повторяющиеся значения, номера назначаются произвольно.
ранг : присваивает уникальный номер для каждой строки, начиная с 1, за исключением строк, имеющих повторяющиеся значения, в этом случае присваивается один и тот же рейтинг, и в последовательности появляется пробел для каждого повторяющегося рейтинга.
вы увидите разницу только в том случае, если у вас есть связи внутри раздела для определенного значения заказа.
RANKиDENSE_RANKявляются детерминированными в этом случае все строки с одинаковым значением для столбцов упорядочения и разбиения будут иметь одинаковый результат, тогда какROW_NUMBERбудет произвольно (недетерминированно) назначать инкрементный результат связанным строкам.пример: (все строки имеют одинаковое
StyleIDтак в тот же раздел и внутри этого раздела первые 3 строки привязываются при заказеID)WITH T(StyleID, ID) AS (SELECT 1,1 UNION ALL SELECT 1,1 UNION ALL SELECT 1,1 UNION ALL SELECT 1,2) SELECT *, RANK() OVER(PARTITION BY StyleID ORDER BY ID) AS 'RANK', ROW_NUMBER() OVER(PARTITION BY StyleID ORDER BY ID) AS 'ROW_NUMBER', DENSE_RANK() OVER(PARTITION BY StyleID ORDER BY ID) AS 'DENSE_RANK' FROM Tвозвращает
StyleID ID RANK ROW_NUMBER DENSE_RANK ----------- -------- --------- --------------- ---------- 1 1 1 1 1 1 1 1 2 1 1 1 1 3 1 1 2 4 4 2вы можете видеть, что для трех одинаковых строк
ROW_NUMBERС шагомRANKзначение остается тем же, то он прыгает в4.DENSE_RANKтакже присваивает одинаковый ранг всем трем строкам, но затем следующему отдельному значению присваивается значение 2.
эта статья охватывает интересные отношения между
ROW_NUMBER()иDENSE_RANK()(theRANK()функция не обрабатывается специально). Когда вам нужен сгенерированныйROW_NUMBER()наSELECT DISTINCTзаявлениеROW_NUMBER()будет производить различные значения до они удаляются с помощьюDISTINCTключевое слово. Например, этот запросSELECT DISTINCT v, ROW_NUMBER() OVER (ORDER BY v) row_number FROM t ORDER BY v, row_number... может привести к этому результату (
DISTINCTне имеет никакого эффекта):+---+------------+ | V | ROW_NUMBER | +---+------------+ | a | 1 | | a | 2 | | a | 3 | | b | 4 | | c | 5 | | c | 6 | | d | 7 | | e | 8 | +---+------------+а это запрос:
SELECT DISTINCT v, DENSE_RANK() OVER (ORDER BY v) row_number FROM t ORDER BY v, row_number... производит то, что вы, вероятно, хотите в этом случае:
+---+------------+ | V | ROW_NUMBER | +---+------------+ | a | 1 | | b | 2 | | c | 3 | | d | 4 | | e | 5 | +---+------------+отметим, что
ORDER BYстатьиDENSE_RANK()функция будет нуждаться во всех других столбцах изSELECT DISTINCTпредложение для правильной работы.причина этого в том, что логически,оконные функции вычисляются до
DISTINCTприменяется.все три функции в сравнении
использование стандарта PostgreSQL / Sybase / SQL синтаксис (
WINDOWпункта):SELECT v, ROW_NUMBER() OVER (window) row_number, RANK() OVER (window) rank, DENSE_RANK() OVER (window) dense_rank FROM t WINDOW window AS (ORDER BY v) ORDER BY v... вы получите:
+---+------------+------+------------+ | V | ROW_NUMBER | RANK | DENSE_RANK | +---+------------+------+------------+ | a | 1 | 1 | 1 | | a | 2 | 1 | 1 | | a | 3 | 1 | 1 | | b | 4 | 4 | 2 | | c | 5 | 5 | 3 | | c | 6 | 5 | 3 | | d | 7 | 7 | 4 | | e | 8 | 8 | 5 | +---+------------+------+------------+
совсем немного:
ранг строки равен единице плюс количество рангов, которые предшествуют рассматриваемой строке.
Row_number-это отдельный ранг строк, без каких-либо пробелов в рейтинге.
посмотреть в этом примере.
CREATE TABLE [dbo].#TestTable( [id] [int] NOT NULL, [create_date] [date] NOT NULL, [info1] [varchar](50) NOT NULL, [info2] [varchar](50) NOT NULL, )вставить некоторые данные
INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (1, '1/1/09', 'Blue', 'Green') INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (1, '1/2/09', 'Red', 'Yellow') INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (1, '1/3/09', 'Orange', 'Purple') INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (2, '1/1/09', 'Yellow', 'Blue') INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (2, '1/5/09', 'Blue', 'Orange') INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (3, '1/2/09', 'Green', 'Purple') INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (3, '1/8/09', 'Red', 'Blue')повторите те же значения для 1
вставить в dbo.#TestTable (id, create_date, info1, info2) значения (1, '1/1/09', 'Синий', 'Зеленый')
Смотреть Всем
SELECT * FROM #TestTableпосмотреть ваши результаты
SELECT Id, create_date, info1, info2, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY create_date DESC) AS RowId, RANK() OVER(PARTITION BY Id ORDER BY create_date DESC) AS [RANK] FROM #TestTableнужно понимать разные
кроме того, обратите внимание на порядок в разделе (например, используется стандартная база данных AdventureWorks) при использовании ранга.
выберите as1.SalesOrderID, as1.SalesOrderDetailID, RANK () OVER (Раздел по as1.Заказ SalesOrderID по as1.SalesOrderID) ranknoequal , RANK () OVER (разбиение на as1.Порядок значения salesorderid по в AS1.SalesOrderDetailId) ranknodiff от продаж.Таблицы salesorderdetail в AS1 Где SalesOrderId = 43659 заказать по SalesOrderDetailId;
дает результат:
SalesOrderID SalesOrderDetailID rank_same_as_partition rank_salesorderdetailid
43659 1 1 1
43659 2 1 2
43659 3 1 3
43659 4 1 4
43659 5 1 5
43659 6 1 6
43659 7 1 7
43659 8 1 8
43659 9 1 9
43659 10 1 10
43659 11 1 11
43659 12 1 12но если изменить заказ для (используйте то :
выберите as1.SalesOrderID, as1.OrderQty, RANK () OVER (PARTITION BY в AS1.Заказ SalesOrderID по as1.SalesOrderID) ranknoequal, ранг() OVER (раздел по as1.Заказ SalesOrderID по as1.OrderQty ) rank_orderqty на продажи.Таблицы salesorderdetail в AS1, где значения salesorderid = 43659 заказа То;
выдает:
SalesOrderID OrderQty rank_salesorderid rank_orderqty
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 2 1 7
43659 2 1 7
43659 3 1 9
43659 3 1 9
43659 4 1 11
43659 6 1 12обратите внимание, как меняется ранг, когда мы используем OrderQty (самый правый столбец второй таблицы) в порядке и как он меняется, когда мы используем SalesOrderDetailID (самый правый столбец первой таблицы) в порядке.
Я ничего не сделал с рангом, но я обнаружил это сегодня с row_number().
select item, name, sold, row_number() over(partition by item order by sold) as row from table_nameэто приведет к некоторым повторяющимся номерам строк, так как в моем случае каждое имя содержит все элементы. Каждый товар будет заказан по тому, сколько было продано.
+--------+------+-----+----+ |glasses |store1| 30 | 1 | |glasses |store2| 35 | 2 | |glasses |store3| 40 | 3 | |shoes |store2| 10 | 1 | |shoes |store1| 20 | 2 | |shoes |store3| 22 | 3 | +--------+------+-----+----+
Comments