1

SQL Server 2008 でストアド プロシージャとして動的クエリを作成していますが、日付 (パラメータとして指定) と日時 (データベースに格納) を比較すると、予期しない結果が得られます。時間部分を考慮せずに2つを比較する方法をいくつか探したところ、次のことがわかりました。

DATEDIFF(day, @d, v.ScheduledDate) = 0

私がこれでやっていることは、指定された日付パラメーターと保存された ScheduledDate が同じであるレコードを見つけようとしていることです (たとえば、 2011 年 2 月 5 日と 2011 年 2 月 5日 11:26:19.157 など、日数に関して) これは私がこれを行うために書いたクエリです:

SET @sql = 'SELECT e.Id, e.FirstName, e.LastName, v.ScheduledDate
            FROM Employee e, Visit v
            WHERE 1=1'
-- Several IF IS NOT NULL statements here

IF @d IS NOT NULL
BEGIN
  SET @sql = @sql + ' AND DATEDIFF(day, ''' + @d + ''',' + 'v.ScheduledDate) = 0
  AND v.EmpId = e.Id '
END
EXEC (@sql)

このクエリにより、その日に訪問が予定されている従業員のすべての ScheduledDates が得られると思います。つまり、ID が 5 と 7 の 2 人の従業員がいて、2011 年 2 月 5 日に ID が 5 と 7 の従業員の 2 つの ScheduleDate エントリが Visit テーブルに存在する場合、このクエリを実行します。ただし、実行すると1行しか返されないようです。(補足として、私が作業している 2 つの ScheduledDate エントリは同じ日にありますが、互いに約 3 時間離れています。数時間は確かにクエリの = を >= 0 または <= 0 に変更すると、期待どおりにより多くの行が取得されますが、奇妙なことに、その特定の日付の単一のエントリしか取得できません。同じ従業員が異なる日に複数の訪問を行っているテーブルには他のレコードがあり、>= 0 または <= 0 を使用すると、それに応じて返されます。たとえば、ID 41 の従業員は 2011 年 10 月 29 日に 3 回訪問しています。 、11-24-2011、および 12-28-2011 であり、DATEDIFF を >= 0 に変更すると、これらの 3 つすべてが返されます。同じ日に訪問を予定しています。ここで私のロジックがどこで間違っているかについて、誰かが洞察を提供できますか? これをテストしているときは、ScheduledDate パラメーターのみを指定していることに注意してください。他のすべてのパラメーターが NULL として挿入されるため、他の IF IS NOT NULL ステートメントはすべて失敗します。>= 0 または <= 0 を使用すると、それに応じて返されます。たとえば、ID 41 の従業員は、2011 年 10 月 29 日、2011 年 11 月 24 日、および 2011 年 12 月 28 日に 3 回訪問し、そのうち 3 回すべてを訪問しました。 DATEDIFF を >= 0 に変更すると返されます。2 人の異なる従業員が同じ日に訪問を予定しているのに、なぜ 1 つのレコードしか返されないのか、まだ混乱しています。ここで私のロジックがどこで間違っているかについて、誰かが洞察を提供できますか? これをテストしているときは、ScheduledDate パラメーターのみを指定していることに注意してください。他のすべてのパラメーターが NULL として挿入されるため、他の IF IS NOT NULL ステートメントはすべて失敗します。>= 0 または <= 0 を使用すると、それに応じて返されます。たとえば、ID 41 の従業員は、2011 年 10 月 29 日、2011 年 11 月 24 日、および 2011 年 12 月 28 日に 3 回訪問し、そのうち 3 回すべてを訪問しました。 DATEDIFF を >= 0 に変更すると返されます。2 人の異なる従業員が同じ日に訪問を予定しているのに、なぜ 1 つのレコードしか返されないのか、まだ混乱しています。ここで私のロジックがどこで間違っているかについて、誰かが洞察を提供できますか? これをテストしているときは、ScheduledDate パラメーターのみを指定していることに注意してください。他のすべてのパラメーターが NULL として挿入されるため、他の IF IS NOT NULL ステートメントはすべて失敗します。2 人の異なる従業員が同じ日に訪問を予定しているのに、なぜ 1 つのレコードしか返されないのかについて、私はまだ混乱しています。ここで私のロジックがどこで間違っているかについて、誰かが洞察を提供できますか? これをテストしているときは、ScheduledDate パラメーターのみを指定していることに注意してください。他のすべてのパラメーターが NULL として挿入されるため、他の IF IS NOT NULL ステートメントはすべて失敗します。2 人の異なる従業員が同じ日に訪問を予定しているのに、なぜ 1 つのレコードしか返されないのかについて、私はまだ混乱しています。ここで私のロジックがどこで間違っているかについて、誰かが洞察を提供できますか? これをテストしているときは、ScheduledDate パラメーターのみを指定していることに注意してください。他のすべてのパラメーターが NULL として挿入されるため、他の IF IS NOT NULL ステートメントはすべて失敗します。

4

4 に答える 4

1

これは詳細ですが、非常に有益です: http://www.sommarskog.se/dyn-search.html

SET @sql = N'SELECT e.Id, e.FirstName, e.LastName, v.ScheduledDate
             FROM Employee e, Visit v
             WHERE v.EmpId = e.Id'

-- Several IF IS NOT NULL statements here
IF @d IS NOT NULL
  SET @sql = @sql + N' AND (v.ScheduledDate >= @date AND v.ScheduledDate < @date + 1)'

-- This stays the same, EVEN if the parameter is NULL and not used
-- This ensures execution plan re-use is available
SET @param_definition = '@date DATETIME,    -- Or whatever type v.ScheduledDate is
                         @smeg INT,
                         @head WHATEVER'

SP_EXECUTESQL
    @sql,
    @param_definition,
    @date = CAST(@d AS DATE),
    @smeg = 0,
    @head = NULL
于 2011-12-23T16:32:49.597 に答える
0

これはかなり遠いかもしれませんが、これまでに説明したすべてのこと(Demsの回答に対するコメントを含む)からの私の最も良い推測は、との間の関係は、によってのみ定義されるのEmployeeではなく、複合キーによって定義され、あなたが欠落しているということです。あなたのjoin/where条件でそれの一部。のようなもの。Visitv.EmpId = e.Idv.EmpId = e.Id AND v.CompanyID = e.CompanyID

于 2011-12-23T17:12:03.853 に答える
0

ベストプラクティスは、日付の時間部分を削除することだと思います

DECLARE @dt DATETIME
SELECT @dt = GETDATE()
SELECT CAST(FLOOR(CAST(@dt AS FLOAT)) AS DATETIME)

次に、単純な古い = を使用して比較できます

于 2011-12-23T16:07:54.117 に答える
0

今日も同じことをしましたそのコード行による動的クエリ)。これは私のコード行でした:

DATEDIFF(day,SchDate,GetDate()) = 0

それは完璧に機能しました。申し訳ありませんが、これ以上お手伝いすることはできませんが、それを 4 回ほど読みましたが、datediff 部分に間違いが見つかりません。私はあなたと同じことをしましたが、問題なく動作しました。ただし、必要に応じて次のようなものを使用できます。

(AND day(@d) = day (v.ScheduledDate)) AND (month(@d) = month(v.ScheduledDate)) AND (year(@d) = year(v.ScheduledDate))

多分それはうまくいくでしょう(ランダムな日付でテストしたところ、うまくいきました)。動的クエリには @d 変数がないため、+@d+ などを追加する必要があることがよくありますが、それは既にわかっています =-)

お役に立てれば!

于 2011-12-23T16:30:37.063 に答える