SQL для замовы запісаў з «масай»

У нас ёсць сістэма, якая апрацоўвае запіс з дапамогай «прыярытэту» нумар у табліцы. Вызначым прыярытэт змесціва табліцы, напрыклад,

UPDATE table
SET priority=3
WHERE processed IS NULL

UPDATE table
SET priority=2
WHERE balance>50

UPDATE table
SET priority=1
WHERE value='blah'

(Калі ласка, ігнараваць той факт, што можа быць «перакрываецца» паміж прыярытэтамі :))

Гэта выдатна працуе - табліца апрацоўваецца ў прыярытэтным парадку, так што ўсе радкі, у якіх слупок «значэнне» з'яўляецца «л» прапрацаваны першымі.

Я атрымаў задачу дадання магчымасці замовіць запісы па задаванай «масе». Напрыклад, мы хацелі б 50% ад апрацоўкі быць прыярытэтам 1, 25% прыярытэт 2 і 25% прыярытэт 3. Такім чынам, з вышэйвыкладзенага, у кожных 100 запісаў 50 з іх былі б тыя, дзе «значэнне» з'яўляецца «бла », 25 з іх будзе дзе" баланс "больш, чым 50 і г.д.

Я спрабую высветліць, як зрабіць гэта: свой род ўзважанай кошту Инкрементирования для «прыярытэту», здавалася б, быць лепш, але я не магу атрымаць маю галаву вакол, як закадаваць гэта. Можа хто-небудзь дапамагчы, калі ласка?

EDIT: Выбачэнні, варта было б сказаць: гэта працуе на MSSQL 2008

5
Якую версію SQL вы карыстаецеся?
дададзена аўтар Curt, крыніца
Опа, на самай справе варта было б згадаць, што. Гэта SQL 2008
дададзена аўтар KenD, крыніца
Значэнне прыярытэту павінна быць абноўлена. Наша сістэма счытвае гэтую табліцу па прыярытэце (эфектыўна SELECT * FROM табліцы парадку прыярытэту).
дададзена аўтар KenD, крыніца
У сапраўдным час Бяжыць заяву ў зваротным парадку (я абнавіў маё пытанне, каб адлюстраваць гэта, прабачце). Гэта азначае, што любы «перакрываецца» маюць найвышэйшы прыярытэт. Я не ўпэўнены, як гэта рэалізаваць з узважваннем, хоць - для прастаты, было б лягчэй выказаць здагадку, што ўзважванне заўсёды робіцца на адным полі, напрыклад, значэнне?
дададзена аўтар KenD, крыніца
@Lieven: Я не лічыў, што :( Было б «ўсе намаганні», каб задаволіць крытэрыі ўзважвання, так і ў выпадку там не дастаткова запісаў у прыярытэце для задавальнення дакладнага адсотка зрыву не будзе велізарным пытанне.
дададзена аўтар KenD, крыніца
@StevieG: Гэта больш верагодна, будзе некаторы дынамічны SQL генеруецца на лета. Запісу не рэгулярна мяняць, вядома, не ў той час як гэты працэс будзе запушчаны.
дададзена аўтар KenD, крыніца
Я не ўпэўнены, я разумею. Ці трэба вам вымаемых запісаў у парадку апісання або мець іх абноўленымі у табліцы?
дададзена аўтар Lieven Keersmaekers, крыніца
Як вы вызначаеце, што прыярытэт 2 (баланс> 50) можа быць зменены на 1?
дададзена аўтар Lieven Keersmaekers, крыніца
Я па-ранейшаму ўзнікаюць праблемы, высвятляючы крайнія выпадкі. Што, калі б вы толькі 4 прыярытэту 3 запісаў у табліцы? Якой павінна быць swichted да 2, і які з іх 1?
дададзена аўтар Lieven Keersmaekers, крыніца
гэта колькасць запісаў рэгулярна змяняецца (г.зн. падчас апрацоўкі прагонаў)? Што робіць апрацоўку - захоўваемая працэдура, ці якой-небудзь за межамі працэсу?
дададзена аўтар StevieG, крыніца

2 адказы

Агульная ідэя заключаецца ў тым, каб сабраць задачы ў вёдры, падзеленыя на мяжы цэлых лікаў:

select
  task_id
from (  
  select 
    task_id, 
    ((task_priority_order - 1)/task_priority_density) as task_processing_order
  from (
    select
      t.task_id                                            as task_id, 
      t.priority                                           as task_priority, 
      row_number() 
        over (partition by t.priority order by t.priority) as task_priority_order,
      case
        when t.priority = 3 then 50
        when t.priority = 2 then 25
        when t.priority = 1 then 25
      end                                                  as task_priority_density
    from
      table t
  )
)
order by task_processing_order

У дыяпазоне ад 0.0 да 0. (9) мы атрымалі 100 запісаў, складзеных з першых 50 запісаў з прыярытэтам 3, першыя 25 запісаў з прыярытэтам 2 і першыя 25 запісаў з прыярытэтам 1.

Наступны дыяпазон ад 1,0 да 1. (9) уяўляе сабой наступнае вядро запісаў.

Калі больш няма задач з некаторым значэннем прыярытэту, то тыя, што засталіся задачы не будуць змешчаны ў вядры ў такім жа суадносінах. напрыклад калі не хапае задач з прыярытэтам 3, то астатнія задачы будуць арганізаваны з суадносінамі 50/50.

TASK_ID - некаторы сурагатным ключ для ідэнтыфікацыі задачы.

пастскрыптум На жаль, я не магу праверыць гэтае пытанне ў цяперашні час, так што любая карэкцыя сінтаксісу вельмі шануецца.

Update: Query syntax corrected according to comments.

5
дададзена
Я змяніў priority_density у task_priority_density у CASE заяву, і я змяніў row_number да row_number() над (раздзел па t.priority ORDER BY t.priority) -1, як task_priority_order - не ўпэўнены, што гэта правільна, але скардзіўся, калі я не зрабіў. Цяпер, здаецца, выдатна працуе з тэставай табліцы; Мне трэба, каб змяніць яго, каб працаваць з сістэмай вытворчасці, але гэта прымушае мяне 90% шляху. Дзякуй вельмі вельмі шмат!
дададзена аўтар KenD, крыніца
@Kenny Андэрсан: Дзякуй за вашыя каментары, адказаць выпраўлена.
дададзена аўтар ThinkJet, крыніца

Дадзены сцэнар тэставання забяспечвае наступную выснову. Калі б выкласці некаторыя правілы аб тым, што канчатковы вынік павінен быць, я гатовы яшчэ раз зірнуць на яго.

<Моцны> Вынікі

Priority    Processed       Balance Value
3           NULL            NULL    NULL
NULL        0               49      NULL
NULL        1               49      NULL
NULL        0               50      NULL
NULL        1               50      NULL
2           0               51      NULL
2           1               51      NULL
2           0               51      Notblah
1           1               51      blah

<Моцны> Тэставы скрыпт

DECLARE @Table TABLE (Priority INTEGER, Processed BIT, Balance INTEGER, Value VARCHAR(32))

INSERT INTO @Table VALUES 
  (NULL, NULL, NULL, NULL)
  , (NULL, 0, 49, NULL)
  , (NULL, 1, 49, NULL)
  , (NULL, 0, 50, NULL)
  , (NULL, 1, 50, NULL)
  , (NULL, 0, 51, NULL)
  , (NULL, 1, 51, NULL)
  , (NULL, 0, 51, 'Notblah')
  , (NULL, 1, 51, 'blah')

UPDATE @table SET priority=3 WHERE processed IS NULL
UPDATE @table SET priority=2 WHERE balance > 50
UPDATE @table SET priority=1 WHERE value = 'blah'

SELECT  *
FROM    @table
0
дададзена