1

4つのフィールド(id、Year、Week、Totals)を持つテーブルがあります。

年と週のフィールドに基づいてゼロ値を入力するには、結合を使用してクエリを実行する必要があります。

私の例では、2013年の第3週と第4週のゼロ値を入力する必要があります

Rec Id, Year, Week, Totals
1, '2012', '52', '23'
2, '2013', '1' , '9'
3, '2013', '2' , '4'

Missing record from DB -> null, '2013', '3' , '0'
Missing record from DB -> null, '2013', '4' , '0'

4, '2013', '5' , '5'
5, '2013', '6' , '6'
6, '2013', '7' , '5'
4

1 に答える 1

1

楽しかったです!OK、どうぞ。まず、いくつかの仮定に依存する簡単なバージョンを紹介します。

  1. 毎年、テーブルに少なくとも1つのエントリがあります
  2. 任意の年について、テーブルには毎週少なくとも1つあります。IE:このクエリは1から52までのすべての数値を返します:

    your_tableからDISTINCT週を選択します

これらの制約を考えると、このクエリは必要なことを実行する必要があります。

INSERT INTO your_table (id, year, week, totals)
    SELECT null, y, w, 0 FROM (
        SELECT DISTINCT week w FROM your_table
    ) weeks
    CROSS JOIN 
    (
        SELECT DISTINCT year y FROM your_table
    ) years
    WHERE
        (y > (select min(year) from your_table) OR w > (select min(week) from your_table where `year`=y))
        AND
        (y < (select max(year) from your_table) OR w < (select max(week) from your_table where `year`=y))
        AND 
        NOT EXISTS (select year, week from your_table where `year`=y AND `week`=w)

条件2が満たされない可能性がある場合-毎年欠落している週がある場合は、この行を置き換えることができます

SELECT DISTINCT week w FROM your_table

SELECT
    (TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue + TWO_32.SeqValue) w
FROM
    (SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 32 SeqValue) TWO_32
HAVING w >= 1 AND w <= 52

このより一般的なケースを与える:

INSERT INTO your_table (id, year, week, totals)
    SELECT null, y, w, 0 FROM (
        SELECT
            (TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue + TWO_32.SeqValue) w
        FROM
            (SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 32 SeqValue) TWO_32
        HAVING w >= 1 AND w <= 52
    ) weeks
    CROSS JOIN 
    (
        SELECT DISTINCT year y FROM your_table
    ) years
    WHERE
        (y > (select min(year) from your_table) OR w > (select min(week) from your_table where `year`=y))
        AND
        (y < (select max(year) from your_table) OR w < (select max(week) from your_table where `year`=y))
        AND 
        NOT EXISTS (select year, week from your_table where `year`=y AND `week`=w)

(条件1が満たされない場合は、同様の手法を使用して年のリストを生成できますが、1年全体の穴がないことを推測しています。)

最後に、年と週に一意のインデックスがある場合、これは少し単純化できます。そのようなインデックスをまだ持っていない場合は、次のように作成できます。

ALTER TABLE `your_table` ADD CONSTRAINT date UNIQUE (
`year`,
`week`
)

必要に応じて、次のように、完了したら削除できます。

ALTER TABLE `your_table` DROP INDEX date;

その場合、where句の最後の部分を削除できます。

AND 
NOT EXISTS (select year, week from your_table where `year`=y AND `week`=w)

INSERT IGNOREは、その一意の年/週の組み合わせがすでに存在する行をスキップするためです。

範囲生成コードに対するこの回答への称賛:https ://stackoverflow.com/a/8349837/160565

于 2013-02-20T00:48:49.510 に答える