0

非常にパフォーマンスに敏感な SQL Server DB を持っています。次の問題を効率的に選択する必要があります。

4つのフィールドを持つ単純なテーブルがあります:

ID [int, PK]
UserID [int, FK]
Active [bit]
GroupID [int, FK]

各 UserID は、Active='false' の GroupID (および複数の groupID) で複数回表示できますが、Active='true' の場合は 1 回だけです。

そのような:

(id,userid,active,groupid)
1,2,false,10
2,2,false,10
3,2,false,10
4,2,true,10

ユーザーの最後のアクティブな状態を保持する必要がある特定のグループのテーブルから、すべての個別のユーザーを選択する必要があります。ユーザーがアクティブな状態にある場合 - ユーザーの非アクティブな状態を返す必要はありません。

単純な解決策は二重選択です。1 つはすべてのアクティブなユーザーを選択し、もう 1 つは最初の select ステートメントに表示されないすべての非アクティブなユーザーを選択します (各ユーザーはある時点で非アクティブな状態になる可能性があるため)。 )。しかし、これは最初の選択 (アクティブなユーザーを含む) を 2 回実行することになり、これは非常に望ましくありません。

必要なクエリを取得するために 1 つだけを選択するスマートな方法はありますか? アイデア?

よろしくお願いします!

4

5 に答える 5

0

これを試して:

Select
   ug.GroupId,
   ug.UserId,
   max(ug.Active) LastState
from
   UserGroup ug
group by
   ug.GroupId,
   ug.UserId

ユーザー/グループの組み合わせに対してアクティブフィールドが1に設定されている場合は、1を取得し、そうでない場合は、最後の状態に対して0を取得します。

于 2011-10-02T14:37:24.193 に答える
0

あなたがやっているように「isActive」列を使用することはあまり好きではありません。これにはUPDATE、アクティブなステータスを変更するのに 2 つの が必要であり、アクティブなステータスに関する情報を異なるレコードに数回格納する効果があります。

代わりに、フィールドを削除してactive、次の 2 つのいずれかを行います。

  1. (userid, groupid)または である (または可能性がある)テーブルがどこかに既にある場合は、PRIMARY KEYそのテーブルに列をUNIQUE INDEX追加します。activeユーザーが特定のグループに関してアクティブまたは非アクティブになった場合、その単一のレコードのみをtrueまたはで更新しfalseます。

  2. そのようなテーブルがまだ存在しない場合は、'(userid, groupid) as thePRIMARY KEY and the fieldactive` を使用してテーブルを作成し、上記のようにテーブルを処理します。

いずれの場合も、特定のグループに関するユーザーのステータスを判断するには、このテーブルを (集計なしで) クエリするだけで済みます。同様に重要なことは、trueまたはfalse値を 1 回だけ保存しUPDATE、ステータスを変更するために必要な値が 1 つだけであることです。最後に、このテーブルは、ステータスの変更ごとに 1 回ではなく、メンバーシップごとに 1 回だけ適用される、そのグループ内のそのユーザーのメンバーシップに固有のその他の情報を格納できる場所として機能します。

于 2011-10-02T15:28:18.387 に答える
0

このようなビューはどうですか:

createview ACTIVE as select * from USERS where Active = TRUE

次に、そのビューから 1 つ選択するだけで十分です。

select user from ACTIVE where ID ....
于 2011-10-02T14:13:16.240 に答える
0

これを試して:

SELECT t.* FROM tbl t 
INNER JOIN (
    SELECT MAX(id) id
    FROM tbl
    GROUP BY userid 
) m
ON t.id = m.id 
于 2011-10-02T20:30:29.517 に答える
0

あなたのクエリが何を返したいのか理解できませんが、とにかく。このクエリは、最後のエントリでアクティブなグループ内のユーザーを提供します。row_number()を使用するため、少なくとも SQL Server 2005 が必要です。

テーブル定義:

create table YourTable
(
  ID int identity primary key,
  UserID int,
  Active bit,
  GroupID int
)

クエリをサポートするインデックス:

create index IX_YourTable_GroupID on YourTable(GroupID) include(UserID, Active)

サンプルデータ:

insert into YourTable values
(1, 0, 10),
(1, 0, 10),
(1, 0, 10),
(1, 1, 10),
(2, 0, 10),
(2, 1, 10),
(2, 0, 10),
(3, 1, 10)

クエリ:

declare @GroupID int = 10

;with C as 
(
  select UserID,
         Active,
         row_number() over(partition by UserID order by ID desc) as rn
  from YourTable as T
  where T.GroupID = @GroupID
)
select UserID
from C
where rn = 1 and
      Active = 1

結果:

UserID
-----------
1
3
于 2011-10-03T05:56:02.303 に答える