4

複数の優先順位を持つキューイング システムを実装しています。各優先度の少なくとも
Y 行 を含む X 行を返すことができるクエリが必要です。

例えば:

キューに 3 つの優先度 (高、中、低) があり、優先度ごとにそれぞれ 3、2、1 行が必要だとします。

テーブルが次のようになっている場合:

-----------------
| Id | Priority |
-----------------
|  1 |     High |
|  2 |     High |
|  3 |     High |
|  4 |     High |
|  5 |   Medium |
|  6 |   Medium |
|  7 |      Low |
-----------------

結合された 3 つの単純なクエリは、(1、2、3、5、6、7) を返します。

SELECT TOP 3 Id FROM tbl WHERE Priority = 'High' UNION
SELECT TOP 2 Id FROM tbl WHERE Priority = 'Medium' UNION
SELECT TOP 1 Id FROM tbl WHERE Priority = 'Low'

ただし、テーブルに特定の優先度が十分に含まれていない場合、問題が発生します。

-----------------
| Id | Priority |
-----------------
|  1 |     High |
|  2 |     High |
|  3 |     High |
|  4 |     High |
|  5 |   Medium |
|  6 |      Low |
|  7 |      Low |
-----------------

返してもらいたいです(1、2、3、4、5、6)。
ギャップを埋めるために最高の優先度を使用します (この場合、十分なメディアがないため、4 番目の高行を使用します)。

これに対応するクエリはありますか、それとも SQL レベルではなくアプリケーション内でフィルタリングする方がよいでしょうか?

4

4 に答える 4

0

for ループでこれを実行するストアド プロシージャをいつでも記述でき (優先度ごとに 1 つずつ、最低から 3 回)、反復ごとに、次の反復で返される値の数を動的に調整できます (優先度の高いループ)。 )これで十分でない場合。

動的とは、次のことを意味します。

SELECT TOP (@count) * FROM SomeTable

count前回の反復で必要に応じて調整された場所。

TOPアプリケーション ロジックでこれを使用する場合の問題は、スロットを埋めるのに十分なデータを取得できるように、より多くのデータ (で使用される最大カウンターの 3 倍) をフェッチするか、DB と再度通信する必要があることです。

少数の場合、予防的な余分な取得は重要ではありません。私の好みは、ストアドプロシージャに含めることです。

ただし、ここで役割を果たす変数がいくつかあります。フェッチする個々の行のサイズ、検索するテーブルとそのインデックスのサイズ、プログラミング アーキテクチャ、ネットワーク構成、カウンター値、優先順位の数などです。

于 2013-05-21T01:09:36.373 に答える
0

SQL Server 2005 以降を使用していると仮定すると、入れ子になったCTEs とランキング関数の組み合わせでうまくいくはずです。

;with A as 
(
select top 3 * from tbl where priority = 'High'
),
A1 as 
(
select id, priority from (
select * from A
union all
select top 2 id, priority from (select *,
ROW_NUMBER() over (order by case when priority = 'Medium' then 1 else 2 end) as ranker
from tbl where priority in ('High', 'Medium') and id
not in (select id from A))Z order by ranker asc
) X
),
A2 as (
select id, priority from (
select * from A1
union all
select top 1 id, priority from (select *, 
ROW_NUMBER() over (order by case when priority = 'Low' then 1 else 2 end) as ranker
from tbl where priority in ('High', 'Low') and id
not in (select id from A1))Z order by ranker asc
) X
)
select * from A2
order by id
于 2013-05-21T01:44:29.920 に答える