1

SQL Server に次のテーブルがあります。

user_id,  value,  date,    action_id
----------------------------------
1          A   1/3/2012     null
1          K   1/4/2012     null
1          B   1/5/2012     null
2          X   1/3/2012     null
2          K   1/4/2012     1
3          K   1/3/2012     null
3          L   1/4/2012     2
3          K   1/5/2012     3
4          K   1/3/2012     null


action_id, state
----------------------------------
1           0
2           1
3           1
4           0
5           1

値が「K」で、アクション ID が null であるか、状態が 1 に設定されている各ユーザーの最新のレコードを返す必要があります。必要な結果セットは次のとおりです。

user_id,  value,  date,    action_id
----------------------------------
3          K   1/5/2012     3
4          K   1/3/2012     null

user_id 1 の場合、最新の値は B で、そのアクション ID は null であるため、これを最新のレコードと見なしますが、値は K ではありません。

user_id 2 の場合、最新の値は K ですが、アクション ID 1 の状態は 0 であるため、X にフォールバックしますが、X は K ではありません。

user_id 3 と 4 は簡単です。

ASP.NET での Linq to SQL クエリに興味がありますが、今のところ T-SQL も問題ありません。

4

4 に答える 4

1

SQL クエリは次のようになります。

Select Top 1 T1.* from Table1 T1
LEFT JOIN Table2  T2
ON T1.action_id = T2.action_id
Where T1.Value = 'K' AND (T1.action_id is null or T2.state = 1)
Order by T1.date desc

LINQ クエリ:

var result  = context.Table1.Where(T1=> T1.Value == "K"
                        && (T1.action_id == null || 
                            context.Table2
                            .Where(T2=>T2.State == 1)
                            .Select(T2 => T2.action_id).Contains(T1.action_id)))
                        .OrderByDescending(T => T.date)
                        .FirstOrDefault();

幸運を !!

于 2012-10-22T16:28:55.870 に答える
0

user_idと日付の組み合わせが一意である場合は、次のアプローチを試すこともできます。インデックスを使用できるようにするには、結合内の述語の順序を取得してください。

    SELECT
        testtable.*
    FROM
        (
            SELECT
                 user_id
                ,MAX(date) LastDate
            FROM
                testtable
            WHERE
                value = 'K'
            GROUP BY
                user_id
        ) tblLastValue
    INNER JOIN
        testtable
    ON
        testtable.user_id = tblLastValue.user_id
    AND
        testtable.date = tblLastValue.LastDate
于 2012-10-23T08:45:07.027 に答える
0

TOP 1これは、データベース内の最新のエントリを選択するだけではなく、仕様で説明されているように、すべてのユーザーの上位エントリを選択します。usersここでは、テーブルの名前がandであると想定していますactions

WITH usersactions as 
  (SELECT 
       u.user_id, 
       u.value, 
       u.date, 
       u.action_id,
       ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
    FROM users u 
    LEFT OUTER JOIN actions a ON u.action_id = a.action_id
    WHERE 
        u.value = 'K' AND 
        (u.action_id  IS NULL OR a.state = 1)
  )
SELECT * FROM usersactions WHERE row = 1

または、CTE を使用したくない場合:

SELECT * FROM  
  (SELECT 
       u.user_id, 
       u.value, 
       u.date, 
       u.action_id,
       ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
    FROM users u 
    LEFT OUTER JOIN actions a ON u.action_id = a.action_id
    WHERE 
        u.value = 'K' AND 
        (u.action_id  IS NULL OR a.state = 1)
  ) useractions
WHERE row = 1
于 2012-10-22T16:34:24.837 に答える
0

このクエリは、目的の結果セットを返します。

    SELECT
        *
    FROM
    (
        SELECT
             user_id
            ,value
            ,date
            ,action_id
            ,ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date DESC) RowNum
        FROM
            testtable
        WHERE
            value = 'K'
    ) testtable
    WHERE
        RowNum = 1
于 2012-10-23T08:38:36.270 に答える