3

C#プロジェクトでLINQ to SQLを使用してクエリを作成していますが、いくつか問題があります...

私がやりたいのは、今日のような最後の4日間(たとえば、金曜日)を選択することです。したがって、金曜日28にいる場合は、次のクエリを実行します。金曜日21、14、7...最後4金曜日ですが、今日はそうではありません。

これは簡単ですが、これは複雑な部分です。たとえば、毎月28日から1日までの月末など、設定した例外をクエリしたくないので、これをクエリしたいとします。 (10月、金曜日):

今日は金曜日26日です。質問したいのですが。

19、12、5、9月28日(今から第4金曜日)ですが、先ほど言ったように、28日は月末なので、最後の金曜日である9月21日を返す必要があり、月末ではありません... I休日も同じ問題ですが、月末まで対応できれば、対応できると思います...

私が欲しいものを理解するためにあなたに良い説明をしたことを願っています...これが私のクエリです。これは機能していますが、例外を処理できません。(フィールドb.dayは各日のIDであり、8は月末を意味し、7は休日を意味します)

var values =
    from b in dc.MyTable
    where // This means end of month
    b.day != 8

    // This triggers to query last 4 days
    && b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-28)
    || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-21)
    || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-14)
    || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-7)
    orderby b.id descending
    group b.valor by b.hora_id into hg
    orderby hg.Key descending

    select new
    {
        Key = hg.Key,
        Max avg = System.Convert.ToInt32(hg.Average() + ((hg.Average() * intOkMas) / 100)),
        Min avg = System.Convert.ToInt32(hg.Average() - ((hg.Average() * intOkMenos) / 100))
    };
4

3 に答える 3

3

クエリを実行する前に、取得する日のリストを準備する必要があります。

// Get the last four days excluding today on the same weekday
var days = Enumerable.Range(1, 4).Select(i => DateTime.Today.AddDays(i * -7));

次に、不要な日を削除します。

// Remove those pesky end-of-month days
days = days.Where(d => d.Day < 28 && d.Day > 1);

取得する日のリストの準備が完了したら、クエリを実行する必要があります。

from b in dc.MyTable
where days.Contains(b.date)  // Translated to SQL: date IN (...)
...

編集:コメントで述べたように、フィルタリングを実行した後でも、合計4日が必要です。したがって、単により多くの日数を生成し、最初の4つを取ります。

var days = Enumerable.Range(1, int.MaxValue - 1)
                     .Select(i => DateTime.Today.AddDays(i * -7))
                     .Where(d => d.Day < 28 && d.Day > 1)
                     .Take(4);

LINQ(および一般的には列挙子)の動作方法により、4日とスキップされた日のみが計算されます。

于 2012-11-07T19:01:29.480 に答える
2

このロジックはLINQステートメントには複雑すぎるように思われるため、行を取得した後に例外コード(月の最終金曜日)を作成することを強くお勧めします。過去4日間を取得する代わりに、過去5日間を取得します。それぞれの月の最終金曜日であるものをすべて削除します。まだ5行ある場合は、最後の行を削除します。

アップデート

var values1 =
  from b in dc.MyTable
  where // This means end of month
  b.day != 8

  // This triggers to query last 4 days
  && b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-28)
  || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-21)
  || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-14)
  || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-7)
  orderby b.id descending
  select b;

//Do stuff with values

var values2 = from b in values2
  group b.valor by b.hora_id into hg
  orderby hg.Key descending

  select new
  {
    Key = hg.Key,
    Max avg = System.Convert.ToInt32(hg.Average() + ((hg.Average() * intOkMas) / 100)),
    Min avg = System.Convert.ToInt32(hg.Average() - ((hg.Average() * intOkMenos) / 100))
  };
于 2012-11-07T18:43:00.843 に答える
2

Allon Guralnekの回答に基づいて、少し変更します。

まず、無限の日付ジェネレーターを作成します。

public IEnumerable<DateTime> GetDaysLikeMe(DateTime currentDate)
{
    DateTime temp = currentDate;
    while(true)
    {
        temp = temp.AddDays(-7);
        yield return temp;
    }
}

次に、追加の基準を満たす日付のみに制限することで、遅延実行を有利に使用できます。

GetDaysLikeMe(DateTime.Now).Where(dt => /* dt meets my criteria */).Take(4)

次に、生成されたこのリストを使用して、上記で提案したAllonGuralnekのようにLINQtoSQLでクエリを実行できます。

from b in dc.MyTable
where days.Contains(b.date)  // Translated to SQL: date IN (...)
...

これには、許容可能な日付に追加の述部を指定しても、少なくとも4つの日付を取り戻すことができるという利点があります。述語の1つが何らかの理由で常にfalseを返す場合に備えて、無限日付ジェネレーターに境界チェックを必ず入れてください(つまり、ジェネレーターは決して終了しません)。

IE:while(temp > currentDate.AddYears(-1))

于 2012-11-07T20:04:20.060 に答える