Utilizzando IBM Informix Dynamic Server 11.50.FC6, posso utilizzare questa sequenza SQL per ottenere il risultato richiesto:
Configurazione
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);
Interrogazione
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;
Risultato
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
Spiegazione
Ci sono voluti una buona dose di sperimentazione per ottenere questo "giusto". Informix ha una funzione di costruzione DATE MDY() che accetta tre argomenti interi:il mese, il giorno e l'anno (il nome è mnemonico). Dispone inoltre di tre funzioni di analisi:GIORNO(), MESE() e ANNO() che restituiscono giorno, mese e anno dell'argomento data. La query interna con FULL JOIN fornisce i risultati con valori nulli su entrambi i lati sinistro e destro. Il criterio in 5 parti nella clausola ON sembra essere necessario; in caso contrario, i criteri nella query esterna devono essere più complessi e confusi, se è possibile farlo funzionare. Quindi i criteri nella selezione esterna assicurano che vengano scelti i dati corretti. Un vantaggio delle espressioni NVL() nella query interna è che le colonne dell'ID negozio sono entrambe uguali e non nulle e nessuna delle colonne della data è nulla, quindi la clausola order by può essere più semplice:sull'ID negozio e su entrambe le colonne della data.
In Informix, sarebbe anche possibile rielaborare le espressioni di data come:
NVL(s1.date, s2.date + 1 UNITS YEAR)
NVL(s2.date, s1.date - 1 UNITS YEAR)
In realtà ci sono più conversioni di tipo in corso dietro le quinte con quella notazione, ma ti dà lo stesso risultato e il calcolo extra probabilmente non è poi così significativo.
C'è anche un problema nell'attesa in Informix; non puoi aggiungere o sottrarre 1 anno ao da qualsiasi 29 febbraio, perché non c'è il 29 febbraio nell'anno successivo o precedente. Dovresti stare attento con i tuoi dati; in caso contrario, potresti finire per confrontare i dati del 29-02-2008 con il 28-02-2009 (oltre a confrontare i dati del 28-02-2008 con il 28-02-2009). Esiste un processo chiamato "contabilità in partita doppia", ma questo non è ciò che si intende con esso e i tuoi calcoli potrebbero essere confusi se "2008-02-29 più 1 anno" è 2009-02-28. Informix genera un errore; non è molto più utile. Potresti codificare una procedura memorizzata, probabilmente, per restituire NULL per il 29-02-2008 più 1 anno poiché non esiste una data con cui confrontare le sue vendite.
Dovresti essere in grado di adattare l'aritmetica della data a MySQL abbastanza facilmente; il resto del codice non deve essere modificato.