3

この派生テーブルを返す SQL スクリプトがあります。

MM/YYYY  Cat    Score
01/2012  Test1  17
02/2012  Test1  19
04/2012  Test1  15
05/2012  Test1  16
07/2012  Test1  14
08/2012  Test1  15
09/2012  Test1  15
12/2012  Test1  11
01/2013  Test2  10
02/2013  Test2  15
03/2013  Test2  13
05/2013  Test2  18
06/2013  Test2  14
08/2013  Test2  15
09/2013  Test2  14
12/2013  Test2  10

ご覧のとおり、いくつかの MM/YYYY (2012 年 3 月、2012 年 6 月、2012 年 11 月など) が欠落しています。

欠落している MM/YYYY を猫と 0 (ゼロ) フォームのスコアで埋めたいと思います。

クエリが実行される範囲のすべての MM/YYYY を含むテーブルを結合しようとしましたが、これは最初に出現した行のみを返し、猫ごとに繰り返されません (それを知っている必要があります)。

私の質問はこれです。結合を使用してこれを行うことができますか、それとも一時テーブルでこれを行う必要がありますか?そして、データを出力します。

AHIGA、LarryR…</p>

4

4 に答える 4

8

カテゴリと範囲内のすべての日付のリストをクロス結合する必要があります。テーブル構造を投稿していないので、構造を少し推測する必要がありますが、カレンダーテーブルがあると仮定すると、次のようなものを使用できます。

SELECT  calendar.Date,
        Category.Cat,
        Score = ISNULL(Scores.Score, 0)
FROM    Calendar
        CROSS JOIN Catogory
        LEFT JOIN Scores
            ON Scores.Cat = Category.Cat
            AND Scores.Date = Calendar.Date
WHERE   Calendar.DayOfMonth = 1;

カレンダー テーブルがない場合は、システム テーブルを使用して日付のリストを生成できますMaster..spt_values

    SELECT  Date = DATEADD(MONTH, Number, '20120101')
    FROM    Master..spt_values
    WHERE   Type = 'P';

ハードコードされた日付「20120101」は、範囲内の最初の日付です。

補遺

空白を埋めるクエリだけでなく、実際に不足している行を挿入する必要がある場合は、次のように使用できます。

INSERT Scores (Date, Cat, Score)
SELECT  calendar.Date,
        Category.Cat,
        Score = 0
FROM    Calendar
        CROSS JOIN Catogory
WHERE   Calendar.DayOfMonth = 1
AND     NOT EXISTS
        (   SELECT  1
            FROM    Scores
            WHERE   Scores.Cat = Category.Cat
            AND     Scores.Date = Calendar.Date
        )

ただし、私の意見では、空白を埋めるクエリを使用してデータを挿入するのは少し時間の無駄です。

于 2013-04-24T21:58:48.977 に答える
1

必要なものを取得するには、ドライバー テーブルから始めて、 を使用しますleft outer join。結果は次のようになります。

select driver.cat, driver.MMYYYY, coalesce(t.score, 0) as score
from (select cat, MMYYYY
      from (select distinct cat  from t) c cross join
           themonths  -- use where to get a date range
     ) driver left outer join
     t
     on t.cat = driver.cat and t.MMMYYYY = driver.MMYYYY
于 2013-04-24T21:58:38.320 に答える
0

「完全なテーブル」から「不完全なテーブル」への左結合を行い、「不完全な」テーブルの日付列をチェックするために where ステートメントを設定します。したがって、選択クエリで不足している結果のみが得られます。その後、前に「テーブル名に挿入」を設定するだけです。

最初の実行では、まだ不完全なテーブルにない 2 つの行が見つかります。したがって、ステートメントによって挿入されinsert into、2 つの行が影響を受けます。2 回目の実行では、select ステートメントの結果に 0 行があるため、何も起こりません。影響を受ける行はありません:-)

サンプル: http://sqlfiddle.com/#!2/895fe/6 (select ステートメントをマークするだけです。insert into ステートメントは、結合がどのように機能するかを確認するだけでなくてもかまいません)

Insert Into supportContacts


Select * FROM 

(

Select
'01/2012' as DDate,   'Test1' as Cat,  17  as Score
UNION 
Select
'02/2012' as DDate,   'Test1' as Cat,  17  as Score
UNION 
Select
'03/2012' as DDate,   'Test1' as Cat,  17  as Score
UNION 
Select
'04/2012' as DDate,   'Test1' as Cat,  17  as Score
UNION 
Select
'05/2012' as DDate,   'Test1' as Cat,  17  as Score

) CompleteTable

LEFT JOIN

(

Select
'01/2012' as DDate,   'Test1' as Cat,  17  as Score
UNION 
Select
'02/2012' as DDate,   'Test1' as Cat,  17  as Score
UNION 
Select
'03/2012' as DDate,   'Test1' as Cat,  17  as Score


) InCompleteTable

ON CompleteTable.DDate = IncompleteTable.DDate

WHERE IncompleteTable.DDate is null
于 2013-04-24T22:02:13.063 に答える
0

これを試してみてください -

DECLARE @temp TABLE (FDOM DATETIME, Cat NVARCHAR(50), Score INT)

INSERT INTO @temp (FDOM, Cat, Score)
VALUES 
    ('20120101', 'Test1', 17),('20120201', 'Test1', 19),
    ('20120401', 'Test1', 15),('20120501', 'Test1', 16),
    ('20120701', 'Test1', 14),('20120801', 'Test1', 15),
    ('20120901', 'Test1', 15),('20121001', 'Test1', 13),
    ('20121201', 'Test1', 11),('20130101', 'Test1', 10),
    ('20130201', 'Test1', 15),('20130301', 'Test1', 13),
    ('20130501', 'Test1', 18),('20130601', 'Test1', 14),
    ('20130801', 'Test1', 15),('20130901', 'Test1', 14),
    ('20131201', 'Test1', 10),('20120601', 'Test2', 10)

;WITH enum AS 
(
    SELECT Cat, StartDate = MIN(FDOM), EndDate = MAX(FDOM)
    FROM @temp
    GROUP BY Cat

    UNION ALL

    SELECT Cat, DATEADD(MONTH, 1, StartDate), EndDate
    FROM enum 
    WHERE StartDate < EndDate
)
SELECT e.StartDate, t.Cat, Score = ISNULL(t.Score, 0)
FROM enum e
LEFT JOIN @temp t ON e.StartDate = t.FDOM AND e.Cat = t.Cat
ORDER BY e.StartDate, t.Cat
于 2013-04-25T07:02:08.837 に答える