2016-04-12 8 views
1

MSSQLで作成された2つのパラメタを持つテーブル値関数 1.終了日 2. 2.週の開始日。SELECT INTOで予期しない結果が発生しました

は、期間テーブルは、単に@NUM_WEEKS -1と-130の間にある場合、私はその後気づい「202」

CREATE FUNCTION [dbo].[Get_Week_Rank] 
( 
    -- Add the parameters for the function here 
    @PERIOD_END DATETIME, 
    @NUM_WEEKS INT 
) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT A.PPERIOD TY_PPERIOD, B.PPERIOD TY_PWKSTART, DATEADD(YY, -1, A.PPERIOD) LY_PPERIOD, DATEADD(YY, -1, B.PPERIOD) LY_PWKSTART, B.CRNK WEEK_RANK FROM (
     SELECT PPERIOD, ROW_NUMBER() OVER (ORDER BY PPERIOD) CRNK FROM PERIODS 
      WHERE PPERIOD BETWEEN DATEADD(WW, @NUM_WEEKS - 1, @PERIOD_END) + 1 AND @PERIOD_END 
     ) AS A 
     JOIN (
      SELECT PPERIOD, ROW_NUMBER() OVER (ORDER BY CRNK % 7) CRNK FROM (
       SELECT PPERIOD, ROW_NUMBER() OVER (ORDER BY PPERIOD) CRNK FROM PERIODS 
        WHERE PPERIOD BETWEEN DATEADD(WW, @NUM_WEEKS, @PERIOD_END) + 1 AND @PERIOD_END 
       ) AS A 
       WHERE CRNK % 7 = 1 
      ) AS B ON (A.CRNK - 1)/7 = B.CRNK 
) 

「19971229」との間のすべての日付と(pPeriodと呼ばれる)1つのカラムを持つテーブルであり、そしてこのクエリを実行するとき、結果が正しいです:

SELECT * INTO #WEEKS FROM GET_WEEK_RANK('20160401', -104) 
SELECT * FROM #WEEKS ORDER BY 1 

しかし、-130以下の任意の数(例えば-156、-208)は、返された結果はすべて間違っています。

Wrong results

あなたはTY_PWKSTARTはすべてTY_PPERIODと同期してアップごちゃ混ぜとされていないことがわかります。私が直接クエリを実行する場合は 、結果は罰金を返す:

SELECT * FROM GET_WEEK_RANK('20160401', -140) 

何の問題だろうか?私はMicrosoft SQL Serverを使用しています。2014

編集結果の画像 ご覧のとおり、両方のクエリは基本的に同じことを行いますが、返される結果は異なります。 SELECT INTOを使用するときの最初のクエリのpWkStartの順序が間違っています。

誤った結果:

SELECT * INTO #WEEK_WRONG FROM GET_WEEK_RANK('20160410', -140) 
SELECT * FROM #WEEK_WRONG ORDER BY 1 

WRONG RESULTS

正しい結果:

CREATE TABLE #WEEK_CORRECT (TY_PPERIOD DATETIME, TY_PWKSTART DATETIME, LY_PPERIOD DATETIME, LY_PWKTART DATETIME, WEEK_RANK INT) 
INSERT INTO #WEEK_CORRECT 
SELECT * FROM GET_WEEK_RANK('20160410', -140) 
SELECT * FROM #WEEK_CORRECT ORDER BY 1 

CORRECT RESULTS

EDIT2: がことが判明私の最初のクエリは予期しない結果を生じていました。私はクエリを修正し、SELECT INTOとINSERT INTOから一貫した結果を得ることができました。 ただ、ここでコードを共有する:

CREATE FUNCTION [dbo].[Get_Week_Rank] 
( 
    @PERIOD_END DATETIME, 
    @NUM_WEEKS INT 
) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT A.PPERIOD TY_PPERIOD, B.PPERIOD TY_PWKSTART, DATEADD(YY, -1, A.PPERIOD) LY_PPERIOD, DATEADD(YY, -1, B.PPERIOD) LY_PWKSTART, B.CRNK + 1 WEEK_RANK FROM (
      SELECT PPERIOD, (ROW_NUMBER() OVER (ORDER BY PPERIOD)-1)/7 CRNK FROM PERIODS 
       WHERE PPERIOD BETWEEN DATEADD(WW, @NUM_WEEKS, @PERIOD_END) + 1 AND @PERIOD_END 
     ) AS A 
     JOIN (
      SELECT PPERIOD, ROW_NUMBER() OVER (ORDER BY PPERIOD)-1 CRNK FROM (
       SELECT PPERIOD , ROW_NUMBER() OVER (PARTITION BY CRNK ORDER BY CRNK) CRNK FROM (
        SELECT PPERIOD, (ROW_NUMBER() OVER (ORDER BY PPERIOD)-1)/7 CRNK FROM PERIODS 
         WHERE PPERIOD BETWEEN DATEADD(WW, @NUM_WEEKS, @PERIOD_END) + 1 AND @PERIOD_END 
        ) AS A 
       ) AS A 
       WHERE CRNK = 1 
      ) AS B ON A.CRNK = B.CRNK 
) 
+0

私はSELECT INTO問題を認識しました。私が一時テーブルを作成してINSERT INTOを使用すると、結果は正常です。 – jmstoh

+0

TVF、ビューまたは選択クエリは間違った値を返しません。彼らは*ボンネットの下で同じ*です。したがって、サーバーのバージョンは関係ありません。他のSELECT文と同じようにコードをデバッグすることができます。さまざまな部分を分離し、さまざまな入力に期待する値を取得し、個々の選択や結合を抽出してテストします。 –

+0

また、問題ありませんSELECT INTOを使用します。 TVFから選択すると予想されるデータが返された場合、SELECT INTOを使用してそのデータで新しいテーブルを生成することができます。 –

答えて

1

をクエリのこの部分が壊れている:

SELECT PPERIOD, ROW_NUMBER() OVER (ORDER BY CRNK % 7) CRNK FROM (
    ... 
) AS A 
WHERE CRNK % 7 = 1 

where句がCRNK % 71に等しいことを確立しているので、ROW_NUMBER()式は行番号を割り当てるために自由です任意の順序で。あなたが十分に提供されていないので

SELECT PPERIOD, ROW_NUMBER() OVER (ORDER BY CRNK) CRNK FROM (
    ... 
) AS A 
WHERE CRNK % 7 = 1 

:私はあなたがまだPPERIODまたはCRNK値が働いているに行番号を割り当てるだろうと推測し、その式がなければならない代わりにすることにより明らかに行番号が割り当てられるの式の場合、各行に割り当てられた値には保証がありません。

+0

ありがとう!はい、私の質問に問題があるようです。私はそれを変更し、一貫した結果を得ることができました。 INSERT INTOとSELECT INTOを使用した面白い方法は別の結果を生成しましたが、あなたが言及したように、それは偶然によって "正しい"だけでした。 – jmstoh

+0

@jmstoh - クエリーオプティマイザに異なる実行プランを選択させるようにクエリに加える可能性のある変更は非常に多くあります。また、突然既存のクエリが別の計画を使用するようになるサーバーまたはデータベース(異なるデータ量、異なるトランザクション履歴、パッチなど)の変更。 –

関連する問題