SQL Server выбирает верхнюю часть в подмножествах?

#sql #sql-server #tsql #sql-server-2008

#sql #sql-server #tsql #sql-server-2008

Вопрос:

У меня есть эти данные:

 Create Table #Some ( ForeignId Int , SubValue UniqueIdentifier , WasRead Bit)
Insert Into #Some Values ( 1 , 'ADEE70A8-E804-4A0C-93AD-00CCCB3DA7DA' , 0 )
Insert Into #Some Values ( 1 , '024EDED5-744B-497A-BFB8-06A0C62DE0AE' , 0 )
Insert Into #Some Values ( 1 , 'C3F255F9-3648-4D8D-8D84-0951BD2D0551' , 0 )
Insert Into #Some Values ( 1 , '25CE8E67-A263-409E-8E7F-1A814EF76524' , 0 )
Insert Into #Some Values ( 2 , '1B339D13-B580-4660-9642-0C0FA9C84D14' , 0 )
Insert Into #Some Values ( 2 , '579C5BD3-EE3A-4789-A57B-0FAD0F7227A2' , 0 )
Insert Into #Some Values ( 3 , '31D1E0F2-5F8A-451B-8114-14DB685E9F53' , 0 )
Insert Into #Some Values ( 3 , '52347A60-4156-401F-8570-15554DD905EF' , 0 )
Insert Into #Some Values ( 3 , '6ECD072E-BC43-4A4C-AACD-1A6C256DCFDE' , 0 )
Insert Into #Some Values ( 3 , '3264625D-94CE-4798-9E4B-2672EDE496BC' , 0 )
  

Мне нужно выбрать первые три строки для каждого внешнего идентификатора, обновить их значение WasPolled до 1 и выдать несколько наборов результатов, но общий размер для всех наборов не может быть больше 8:

установить:

 1 , 'ADEE70A8-E804-4A0C-93AD-00CCCB3DA7DA' 
1 , '024EDED5-744B-497A-BFB8-06A0C62DE0AE' 
1 , 'C3F255F9-3648-4D8D-8D84-0951BD2D0551' 
  

установить:

 2 , '1B339D13-B580-4660-9642-0C0FA9C84D14' 
2 , '579C5BD3-EE3A-4789-A57B-0FAD0F7227A2' 
  

установить:

 3 , '31D1E0F2-5F8A-451B-8114-14DB685E9F53' 
3 , '52347A60-4156-401F-8570-15554DD905EF' 
3 , '6ECD072E-BC43-4A4C-AACD-1A6C256DCFDE' 
  

Ответ №1:

 with cte as
(
    select ForeignId, SubValue, row_number() over(partition by ForeignId order by SubValue) as RowNumber
    from #Some
    where WasRead = 0
)
update top (8) s
set WasRead = 1
from #Some s
    join cte on
        cte.ForeignId = s.ForeignId and cte.SubValue = s.SubValue
where cte.RowNumber <= 3;
  

Я не знаю, есть ли у вас первичный ключ. Если вы используете его для объединения. Я предположил, что ForeignId вложенное значение уникально

Ответ №2:

Вот как вы обновили бы первые три строки — вам нужно предоставить средство упорядочения данных:

 WITH example AS (
  SELECT t.*, 
         ROW_NUMBER() OVER(PARTITION BY t.foreignid 
                               ORDER BY t.subvalue) AS rank
    FROM #some t)
UPDATE example
   SET wasread = 1
 WHERE rank BETWEEN 1 AND 3
  

«выдает несколько наборов результатов, но общий размер для всех наборов не может быть больше 8:» — А?! Что вы подразумеваете под «испускать». Выбор означает отдельную инструкцию:

Версия, отличная от CTE:

   SELECT x.*
    FROM (SELECT t.*, 
                 ROW_NUMBER() OVER(PARTITION BY t.foreignid 
                                       ORDER BY t.subvalue) AS rank
            FROM #some t) x
   WHERE x.rank BETWEEN 1 AND 8
  

Версия CTE:

 WITH example AS (
  SELECT t.*, 
         ROW_NUMBER() OVER(PARTITION BY t.foreignid 
                               ORDER BY t.subvalue) AS rank
    FROM #some t)
SELECT e.*
  FROM example e
 WHERE e.rank BETWEEN 1 AND 8
  

Комментарии:

1. Потрясающе, CTE находятся там, где они есть. Спасибо!

Ответ №3:

Используйте функции ранжирования, в частности ROW_NUMBER , чтобы ограничить количество возвращаемых результатов.