4

LINQ 選択を作成するのに助けが必要です。いくつかの列を含むテーブルがありますが、この問題に関係するのは 2 つだけです。

userid, type

現在、このテーブルには何千ものエントリがあり、一番上のものだけが必要です。たとえば、50 としましょう。ここまでは順調ですが、難しいのは、1 としてカウントする必要がある成功した行がたくさんあることです。例

Type  UserId
============
Add   1
Add   1
Add   1
Add   2

取り出している行の制限でこれを2つだけとしてカウントしたいのですが、すべての行をまだ出力したいと思います。これは単一の SQL リクエストで可能ですか、それとも別の方法を見つける必要がありますか?

編集:これで問題が解決する場合は、値を使用してテーブルに列を追加できます。Edit2: sotred 手順も解決策です

例 2: これは 3 行としてカウントする必要があります

Type  UserId
============
Add   1
Add   1
Add   2
Add   1
4

4 に答える 4

1

LINQ でこれを行うことができますが、「for(each) ループ」ルートに進む方が簡単かもしれないと思います...

data.Select((x, i) => new { x.Type, x.UserId, i })
    .GroupBy(x => x.Type)
    .Select(g => new
    {
        Type = g.Key,
        Items = g
            .Select((x, j) => new { x.UserId, i = x.i - j })
    })
    .SelectMany(g => g.Select(x => new { g.Type, x.UserId, x.i }))
    .GroupBy(x => new { x.Type, x.i })
    .Take(50);
    .SelectMany(g => g.Select(x => new { x.Type, x.UserId }));
于 2013-04-04T22:27:01.387 に答える
1

私は今のところコンピューターの近くにいないので、構文が 100% 正しいかどうかはわかりませんが、次のようなものを探していると思います。

data.Select(x => new {x.Type, x.UserId})
    .GroupBy(x => x.UserId)
    .Take(50);
于 2013-04-04T21:29:12.750 に答える
1

Linq でそれを行うこともできますが、従来のループよりもかなり遅くなる可能性がありますfor。1つの方法は次のとおりです。

data.Where((s, i) => i == 0 || 
                     !(s.Type == data[i-1].Type && s.UserId == data[i-1].UserId))

これにより、「前の」アイテムと同じ Type と UserID を持つ「重複した」アイテムはスキップされます。

ただし、これdataはインデクサー (配列または を実装するものIList) がある場合にのみ機能します。IEnumerableorは機能しIQueryableません。また、ほぼ確実に SQL に変換できないため、すべての結果を取得してメモリ内でフィルター処理する必要があります。

SQL で実行する場合は、値の 1 つが変更された場合はカーソルをスキャンして一時テーブルに入力するか、ROW_NUMBER列を含む共通のテーブル式を使用してから、Linq に似たルックバック サブクエリを実行します。上記の方法:

WITH base AS
(
SELECT 
    Type,
    UserId, 
    ROW_NUMBER() OVER (ORDER BY ??? ) AS RowNum
    FROM Table
)
SELECT b1.Type, b1.UserId
FROM base b1
LEFT JOIN base b2 ON b1.RowNum = b2.RowNum - 1
WHERE (b1.Type <> b2.Type OR b1.UserId <> b2.UserId)
ORDER BY b1.RowNum
于 2013-04-04T21:58:14.233 に答える