IBM Informix Dynamic Server 11.50.FC6を使用すると、このSQLシーケンスを使用して、必要な結果を得ることができます。
セットアップ
CREATE TABLE sales
(
id INTEGER NOT NULL,
id_store INTEGER NOT NULL,
date DATE NOT NULL,
total DECIMAL(10,2) NOT NULL
);
INSERT INTO sales VALUES( 1, 1, '2010-01-01', 500.00);
INSERT INTO sales VALUES( 2, 1, '2010-01-02', 185.00);
INSERT INTO sales VALUES( 3, 1, '2010-01-03', 135.00);
INSERT INTO sales VALUES( 4, 1, '2009-01-01', 165.00);
INSERT INTO sales VALUES( 5, 1, '2009-01-02', 175.00);
INSERT INTO sales VALUES( 6, 5, '2010-01-01', 130.00);
INSERT INTO sales VALUES( 7, 5, '2010-01-02', 135.00);
INSERT INTO sales VALUES( 8, 5, '2010-01-03', 130.00);
INSERT INTO sales VALUES( 9, 6, '2010-01-01', 100.00);
INSERT INTO sales VALUES(10, 6, '2010-01-02', 12.00);
INSERT INTO sales VALUES(11, 6, '2010-01-03', 85.00);
INSERT INTO sales VALUES(12, 6, '2009-01-01', 135.00);
INSERT INTO sales VALUES(13, 6, '2009-01-02', 400.00);
INSERT INTO sales VALUES(14, 6, '2009-01-07', 21.00);
INSERT INTO sales VALUES(15, 6, '2009-01-08', 45.00);
INSERT INTO sales VALUES(16, 8, '2009-01-09', 123.00);
INSERT INTO sales VALUES(17, 8, '2009-01-10', 581.00);
クエリ
SELECT *
FROM (SELECT s1.id AS s1id,
NVL(s1.id_store, s2.id_store) AS s1store,
NVL(s1.date, MDY(MONTH(s2.date), DAY(s2.date),
YEAR(s2.date)+1)) AS s1date,
s1.total AS s1total,
s2.id AS s2id,
NVL(s2.id_store, s1.id_store) AS s2store,
NVL(s2.date, MDY(MONTH(s1.date), DAY(s1.date),
YEAR(s1.date)-1)) AS s2date,
s2.total AS s2total
FROM sales AS s1 FULL JOIN sales AS s2
ON s1.id_store = s2.id_store
AND s1.date BETWEEN '2010-01-01' AND '2010-01-10'
AND s2.date BETWEEN '2009-01-01' AND '2009-01-10'
AND DAY(s1.date) = DAY(s2.date)
AND MONTH(s1.date) = MONTH(s2.date)
) AS s3
WHERE s1_date BETWEEN '2010-01-01' AND '2010-01-10'
AND s2_date BETWEEN '2009-01-01' AND '2009-01-10'
ORDER BY s1_id_store ASC, s1_date ASC;
結果
s1id s1store s1date s1total s2id s2store s2date s2total
1 1 2010-01-01 500.00 4 1 2009-01-01 165.00
2 1 2010-01-02 185.00 5 1 2009-01-02 175.00
3 1 2010-01-03 135.00 1 2009-01-03
6 5 2010-01-01 130.00 5 2009-01-01
7 5 2010-01-02 135.00 5 2009-01-02
8 5 2010-01-03 130.00 5 2009-01-03
9 6 2010-01-01 100.00 12 6 2009-01-01 135.00
10 6 2010-01-02 12.00 13 6 2009-01-02 400.00
11 6 2010-01-03 85.00 6 2009-01-03
6 2010-01-07 14 6 2009-01-07 21.00
6 2010-01-08 15 6 2009-01-08 45.00
8 2010-01-09 16 8 2009-01-09 123.00
8 2010-01-10 17 8 2009-01-10 581.00
説明
これを「正しく」するためには、かなりの実験が必要でした。 Informixには、月、日、年の3つの整数引数をとるDATEコンストラクター関数MDY()があります(名前はニーモニックです)。また、3つの分析関数、DAY()、MONTH()、およびYEAR()があり、日付引数の日、月、および年を返します。 FULL JOINを使用した内部クエリでは、左側と右側の両方にnullが含まれる結果が得られます。 ON句の5つの部分からなる基準が必要と思われます。それ以外の場合、外部クエリの基準は、より複雑で混乱を招く必要があります。次に、外側の選択の基準により、適切なデータが選択されていることが保証されます。内部クエリのNVL()式の利点の1つは、ストアID列が同じでnullではなく、どちらの日付列もnullでないことです。そのため、ストアIDといずれかの日付列でのorderby句が簡単になります。
Informixでは、日付式を次のように作り直すこともできます。
NVL(s1.date, s2.date + 1 UNITS YEAR)
NVL(s2.date, s1.date - 1 UNITS YEAR)
実際には、その表記法で舞台裏で複数の型変換が行われていますが、同じ結果が得られ、余分な計算はおそらくそれほど重要ではありません。
Informixでの待機にも問題があります。 2月29日には1年を加算または減算することはできません。これは、翌年または前年に2月29日がないためです。データに注意する必要があります。そうでない場合は、2008-02-29のデータを2009-02-28と比較する(および2008-02-28のデータを2009-02-28と比較する)ことになる可能性があります。 「複式簿記」と呼ばれるプロセスがありますが、これはそれが意味するものではなく、「2008-02-29プラス1年」が2009-02-28の場合、計算が混乱する可能性があります。 Informixはエラーを生成します。それはあまり役に立ちません。おそらく、売上を比較する日付がないため、2008-02-29に1年を加えたNULLを返すようにストアドプロシージャをコーディングする場合があります。
日付演算をMySQLにかなり簡単に適応させることができるはずです。残りのコードを変更する必要はありません。