アプリ版:「スタンプのみでお礼する」機能のリリースについて

MySQLの自己結合を使って、3日間の売上データを同じ列に表示するプログラムを作っています。
日付が連続している場合(当日、1日前、2日前)のSQL文は作れたのですが、日付が飛んでいる(日付に抜けのある)場合のSQL文がうまく作れません。
どのようなSQL文を作成すればよいか教えていただければと思います。

テーブル名: sales2
カラム: id,product_id(製品コード),date(営業日),volume(売上)

----------------------------------------
3日間の売上データ(日付に抜けが無い場合)
----------------------------------------

SELECT A.id, A.product_id, A.date, A.volume, B.volume AS volumeB, C.volume AS volumeC
FROM sales2 AS A
INNER JOIN sales2 AS B ON A.product_id = B.product_id
AND A.date = DATE( B.date + INTERVAL 1 DAY )
INNER JOIN sales2 AS C ON A.product_id = C.product_id
AND A.date = DATE( C.date + INTERVAL 2 DAY )
ORDER BY A.product_id ASC , A.date DESC


+----+------------+------------+--------+---------+---------+
| id | product_id | date | volume | volumeB | volumeC |
+----+------------+------------+--------+---------+---------+
| 21 | 1 | 2017-01-10 | 57 | 12 | 88 |
| 20 | 1 | 2017-01-09 | 12 | 88 | 96 |
| 19 | 1 | 2017-01-08 | 88 | 96 | 28 |
| 18 | 1 | 2017-01-07 | 96 | 28 | 19 |
| 17 | 1 | 2017-01-06 | 28 | 19 | 70 |
| 27 | 1 | 2017-01-05 | 19 | 70 | 20 |
| 12 | 1 | 2017-01-04 | 70 | 20 | 30 |
| 11 | 1 | 2017-01-03 | 20 | 30 | 10 |
| 26 | 2 | 2017-01-10 | 60 | 90 | 29 |
| 25 | 2 | 2017-01-09 | 90 | 29 | 79 |
| 24 | 2 | 2017-01-08 | 29 | 79 | 26 |
| 23 | 2 | 2017-01-07 | 79 | 26 | 33 |
| 22 | 2 | 2017-01-06 | 26 | 33 | 64 |
| 28 | 2 | 2017-01-05 | 33 | 64 | 86 |
| 16 | 2 | 2017-01-04 | 64 | 86 | 30 |
| 15 | 2 | 2017-01-03 | 86 | 30 | 55 |
+----+------------+------------+--------+---------+---------+
16 rows in set (0.01 sec)


----------------------------------------
試してみたこと
----------------------------------------
volumeは当日の売上、volumeBは1日前の売上、volumeCは2日前の売上になっています。
DATE( C.date + INTERVAL 2 DAY ) の部分でサブクエリを使って当日より前の日付で最大のものを1つ抽出するようにすればよいと思い試しましたが、うまくいきませんでした。

----------------------------------
テストデータ
----------------------------------

CREATE TABLE IF NOT EXISTS `sales2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`volume` int(11) NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=29 ;


INSERT INTO `sales2` (`id`, `product_id`, `volume`, `date`) VALUES
(9, 1, 10, '2017-01-01'),
(10, 1, 30, '2017-01-02'),
(11, 1, 20, '2017-01-03'),
(12, 1, 70, '2017-01-04'),
(13, 2, 55, '2017-01-01'),
(14, 2, 30, '2017-01-02'),
(15, 2, 86, '2017-01-03'),
(16, 2, 64, '2017-01-04'),
(17, 1, 28, '2017-01-06'),
(18, 1, 96, '2017-01-07'),
(19, 1, 88, '2017-01-08'),
(20, 1, 12, '2017-01-09'),
(21, 1, 57, '2017-01-10'),
(22, 2, 26, '2017-01-06'),
(23, 2, 79, '2017-01-07'),
(24, 2, 29, '2017-01-08'),
(25, 2, 90, '2017-01-09'),
(26, 2, 60, '2017-01-10'),
(27, 1, 19, '2017-01-05'),
(28, 2, 33, '2017-01-05');

A 回答 (2件)

調整しました



select
t4.id,t4.product_id,t4.date,t4.volume,t5.volume as volume2,t6.volume as volume3
from (
select t1.id,t1.product_id,t1.volume,t1.date
,(select max(t2.date) from `sales2` as t2 where t1.date>t2.date and t1.product_id=t2.product_id) as t2_date
,(select max(t3.date) from `sales2` as t3 where t2_date>t3.date and t1.product_id=t3.product_id) as t3_date
from `sales2` as t1
having t3_date is not null
) as t4
inner join `sales2` as t5
on t5.date=t2_date
and t4.product_id=t5.product_id
inner join `sales2` as t6
on t6.date=t3_date
and t4.product_id=t6.product_id
order by t4.product_id asc,t4.date desc
    • good
    • 0
この回答へのお礼

yambejp様

ご回答ありがとうございました。求める結果を得ることができました。
このような集計は現在作っているプログラムで多用することになるので、本当に助かりました。
今後とも宜しくお願い致します。

お礼日時:2017/05/01 22:06

SELECT * FROM `sales2` as t1


inner join `sales2` as t2
on t1.date=t2.date + interval 1 day
and t1.product_id=t2.product_id
inner join `sales2` as t3
on t1.date=t3.date + interval 2 day
and t1.product_id=t3.product_id
order by t1.product_id asc, t1.date desc
    • good
    • 0
この回答へのお礼

yambejp 様

ご回答ありがとうございます。
ご提示のSQL文で、日付が無い日のデータが含まれる場合、データが表示されないことが確認できました。

わたくしの質問がうまく書けていなかったようです。お手数かけて申し訳ありません。求めている結果は以下のようなものになります。

「データ」
2017-01-01
2017-01-02
2017-01-03
2017-01-04
2017-01-05
2017-01-06
[2017-01-07が無い]
2017-01-08
2019-01-09
2017-01-10


「求める出力」
2017-01-10 2019-01-09 2017-01-08
2017-01-09 2019-01-08 2017-01-06 ※1
2017-01-08 2019-01-06 2017-01-05 ※2
2017-01-06 2019-01-05 2017-01-04
:::

2017-01-07が無いので、その場合はその前の日のデータを取得する。
元のデータは連続して2日抜けていたり、3日抜けていたり、1日おきにデータが抜けていたりします。(土日、休祝日のデータが無いような形です)

大変お手数をお掛けいたしますが、再度ご回答頂ければと思います。宜しくお願いいたします。

お礼日時:2017/04/28 23:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!