Med IBM Informix Dynamic Server 11.50.FC6 kan jag använda den här SQL-sekvensen för att få det resultat du behöver:
Inställningar
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);
Fråga
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;
Resultat
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
Förklaring
Det krävdes en hel del experiment för att få det här "rätt". Informix har en DATE-konstruktorfunktion MDY() som tar tre heltalsargument:månad, dag och år (namnet är mnemonisk). Den har också tre analysfunktioner:DAY(), MONTH() och YEAR() som returnerar dagen, månaden och året för datumargumentet. Den inre frågan med FULL JOIN ger dig resultaten med nollor på både vänster och höger sida. Det 5-delade kriteriet i ON-klausulen verkar vara nödvändigt; annars måste kriterierna i den yttre frågan vara mer komplexa och förvirrande - om det överhuvudtaget kan fås att fungera. Då säkerställer kriterierna i det yttre urvalet att rätt data väljs. En fördel med NVL()-uttrycken i den inre frågan är att butiks-ID-kolumnerna både är desamma och inte null och att ingen av datumkolumnerna är null, så order by-satsen kan vara enklare - på butiks-ID och endera datumkolumnen.
I Informix skulle det också vara möjligt att omarbeta datumuttrycken som:
NVL(s1.date, s2.date + 1 UNITS YEAR)
NVL(s2.date, s1.date - 1 UNITS YEAR)
Det pågår faktiskt flera typkonverteringar bakom kulisserna med den notationen, men det ger dig samma resultat och den extra beräkningen är förmodligen inte så signifikant.
Det finns också ett fel i väntan i Informix; du kan inte lägga till eller subtrahera 1 år till eller från någon 29 februari - eftersom det inte finns någon 29 februari följande eller föregående år. Du skulle behöva vara försiktig med dina data; om du inte är det kan du sluta med att jämföra uppgifterna för 2008-02-29 med 2009-02-28 (liksom att jämföra uppgifterna för 2008-02-28 med 2009-02-28). Det finns en process som kallas "dubbel bokföring", men det är inte vad som menas med det, och dina beräkningar kan bli förvirrade om "2008-02-29 plus 1 år" är 2009-02-28. Informix genererar ett fel; det är inte så mycket mer användbart. Du kanske kodar en lagrad procedur för att returnera NULL för 2008-02-29 plus 1 år eftersom det inte finns något datum att jämföra försäljningen med.
Du bör kunna anpassa datumräkningen till MySQL ganska enkelt; resten av koden behöver inte ändras.