teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

7

追記

2016/11/17 20:04

投稿

退会済みユーザー
answer CHANGED
@@ -105,6 +105,7 @@
105
105
  ```
106
106
 
107
107
  残業時間、深夜勤務時間を算出し、日給を計算
108
+ (多分、MySQLでしか動かないだろうけど...)
108
109
 
109
110
  ```sql
110
111
  SELECT

6

追記

2016/11/17 20:04

投稿

退会済みユーザー
answer CHANGED
@@ -90,3 +90,57 @@
90
90
  INNER JOIN Staff st ON sf.staff_id = st.id
91
91
  ```
92
92
  ![イメージ説明](8afe930b0a1dc1e8d7a2939cc22b48ee.png)
93
+
94
+ #ついでにおまけ
95
+
96
+ スタッフテーブルに「時給」を追加
97
+
98
+ ```sql
99
+ CREATE TABLE `Staff` (
100
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'PK',
101
+ `name` varchar(32) DEFAULT NULL COMMENT 'スタッフ名',
102
+ `salery` int(11) DEFAULT NULL COMMENT '時給',
103
+ PRIMARY KEY (`id`)
104
+ ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
105
+ ```
106
+
107
+ 残業時間、深夜勤務時間を算出し、日給を計算
108
+
109
+ ```sql
110
+ SELECT
111
+ st.name AS 'スタッフ名'
112
+ , DATE_FORMAT(sf.start, '%Y年%m月%d日') AS '勤務日'
113
+ , sf.start AS '勤務開始日時'
114
+ , sf.end AS '勤務終了日時'
115
+ , TIME_FORMAT(sf.start, '%H:%i') AS '勤務開始時間'
116
+ , IF(
117
+ DATEDIFF(sf.end,sf.start)>0
118
+ , concat(TIME_FORMAT(sf.end, '%H') + 24 * DATEDIFF(sf.end,sf.start), ':', TIME_FORMAT(sf.end, '%i'))
119
+ , TIME_FORMAT(sf.end, '%H:%i')
120
+ ) AS '勤務終了時間'
121
+ , @hour:=HOUR(TIMEDIFF(sf.end,sf.start)) + MINUTE(TIMEDIFF(sf.end,sf.start)) / 60 AS '勤務時間(h)'
122
+ , @exceed:=IF(
123
+ HOUR(TIMEDIFF(sf.end,sf.start)) + MINUTE(TIMEDIFF(sf.end,sf.start)) / 60 - 8 > 0
124
+ , HOUR(TIMEDIFF(sf.end,sf.start)) + MINUTE(TIMEDIFF(sf.end,sf.start)) / 60 - 8
125
+ , 0
126
+ ) AS '残業時間(h)'
127
+ , @night:=HOUR(
128
+ TIMEDIFF(
129
+ LEAST(sf.end, DATE_FORMAT(ADDDATE(DATE(sf.start), INTERVAL +1 DAY), '%Y-%m-%d 07:00:00'))
130
+ , GREATEST(sf.start, STR_TO_DATE(CONCAT(DATE(sf.start), '22:00:00'), '%Y-%m-%d %H:%i:%s'))
131
+ )
132
+ )
133
+ +
134
+ MINUTE(
135
+ TIMEDIFF(
136
+ LEAST(sf.end, DATE_FORMAT(ADDDATE(DATE(sf.start), INTERVAL +1 DAY), '%Y-%m-%d 07:00:00'))
137
+ , GREATEST(sf.start, STR_TO_DATE(CONCAT(DATE(sf.start), '22:00:00'), '%Y-%m-%d %H:%i:%s'))
138
+ )
139
+ ) AS '深夜勤務(h)'
140
+ , st.salery AS '時給'
141
+ , FLOOR(@hour * st.salery + @exceed * st.salery * 0.25 + @night * st.salery * 0.25) AS '給与'
142
+ FROM Shift sf
143
+ INNER JOIN Staff st ON sf.staff_id = st.id
144
+ ```
145
+
146
+ ![イメージ説明](d5489cb0236a9d4722b6baa49f4270f4.png)

5

追記

2016/11/17 20:01

投稿

退会済みユーザー
answer CHANGED
@@ -69,6 +69,13 @@
69
69
 
70
70
  ---
71
71
 
72
+ #以下のコメントに対する回答
73
+
74
+ > 取得はそれで大丈夫ですが、表示する場合です。1日は何時から何時まで, 2日は何時から何時まで、という風に。カレンダーのように表示するのもいいですが。
75
+ 表示する場合は、先ほど行ったように、同じ日にシフトが二つ表示される場合などありませんか?
76
+
77
+ > 登録時に1日の25時から26時(UI)で登録したのに、いざ一覧表示を見てみると2日にシフトがある。実質は変わりないのですが、使用するユーザからするとおかしな挙動になりませんか?
78
+
72
79
  ```sql
73
80
  SELECT
74
81
  st.name AS 'スタッフ名'

4

追記

2016/11/17 18:26

投稿

退会済みユーザー
answer CHANGED
@@ -65,4 +65,21 @@
65
65
 
66
66
  | id | staff_id | start | end | name |
67
67
  |:-:|:-:|:-:|:-:|:-:|
68
- | 1 | 1 | 2017-01-01 23:00:00 | 2017-01-02 01:00:00 | お客さん |
68
+ | 1 | 1 | 2017-01-01 23:00:00 | 2017-01-02 01:00:00 | お客さん |
69
+
70
+ ---
71
+
72
+ ```sql
73
+ SELECT
74
+ st.name AS 'スタッフ名'
75
+ , DATE_FORMAT(sf.start, '%Y年%m月%d日') AS '勤務日'
76
+ , TIME_FORMAT(sf.start, '%H:%i') AS '勤務開始時間'
77
+ , IF(
78
+ DATEDIFF(sf.end,sf.start)>0
79
+ , concat(TIME_FORMAT(sf.end, '%H') + 24 * DATEDIFF(sf.end,sf.start), ':', TIME_FORMAT(sf.end, '%i'))
80
+ , TIME_FORMAT(sf.end, '%H:%i')
81
+ ) AS '勤務終了時間'
82
+ FROM Shift sf
83
+ INNER JOIN Staff st ON sf.staff_id = st.id
84
+ ```
85
+ ![イメージ説明](8afe930b0a1dc1e8d7a2939cc22b48ee.png)

3

追記

2016/11/17 18:11

投稿

退会済みユーザー
answer CHANGED
@@ -48,6 +48,7 @@
48
48
  | id | staff_id | start | end |
49
49
  |:-:|:-:|:-:|:-:|
50
50
  | 1 | 1 | 2017-01-01 22:00:00 | 2017-01-02 02:00:00 |
51
+ | 1 | 1 | 2017-01-02 22:00:00 | 2017-01-03 02:00:00 |
51
52
 
52
53
  ##予約テーブル
53
54
 

2

追記

2016/11/17 17:34

投稿

退会済みユーザー
answer CHANGED
@@ -13,4 +13,55 @@
13
13
 
14
14
  シフトの日付は不要
15
15
 
16
- datetime型で start, datetime型で end を持っていればすむことでは?
16
+ datetime型で start, datetime型で end を持っていればすむことでは?
17
+
18
+ ---
19
+
20
+ これで、イメージできるんじゃないかと思いますが。
21
+
22
+ #データベース定義
23
+
24
+ ##スタッフテーブル
25
+
26
+ ```sql
27
+ CREATE TABLE `Staff` (
28
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'PK',
29
+ `name` varchar(32) DEFAULT NULL COMMENT 'スタッフ名',
30
+ PRIMARY KEY (`id`)
31
+ ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
32
+ ```
33
+ | id | name |
34
+ |:-:|:-:|
35
+ | 1 | スタッフ名 |
36
+
37
+ ##シフトテーブル
38
+
39
+ ```sql
40
+ CREATE TABLE `Shift` (
41
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'PK',
42
+ `staff_id` int(11) DEFAULT NULL COMMENT 'スタッフID',
43
+ `start` datetime DEFAULT NULL COMMENT '勤務開始日時',
44
+ `end` datetime DEFAULT NULL COMMENT '勤務終了日時',
45
+ PRIMARY KEY (`id`)
46
+ ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
47
+ ```
48
+ | id | staff_id | start | end |
49
+ |:-:|:-:|:-:|:-:|
50
+ | 1 | 1 | 2017-01-01 22:00:00 | 2017-01-02 02:00:00 |
51
+
52
+ ##予約テーブル
53
+
54
+ ```sql
55
+ CREATE TABLE `Reserv` (
56
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'PK',
57
+ `staff_id` int(11) DEFAULT NULL COMMENT 'スタッフID',
58
+ `start` datetime DEFAULT NULL COMMENT '開始日時',
59
+ `end` datetime DEFAULT NULL COMMENT '終了日時',
60
+ `name` varchar(32) DEFAULT NULL COMMENT '予約氏名',
61
+ PRIMARY KEY (`id`)
62
+ ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
63
+ ```
64
+
65
+ | id | staff_id | start | end | name |
66
+ |:-:|:-:|:-:|:-:|:-:|
67
+ | 1 | 1 | 2017-01-01 23:00:00 | 2017-01-02 01:00:00 | お客さん |

1

追記

2016/11/17 17:09

投稿

退会済みユーザー
answer CHANGED
@@ -1,4 +1,16 @@
1
1
  > シフトテーブルは日毎に作成している
2
2
 
3
3
  ここがすべての問題の元凶でしょう。
4
- 日毎にテーブルが増えるなんてゆうのは、アンチパターンの代表格です。
4
+ 日毎にテーブルが増えるなんてゆうのは、アンチパターンの代表格です。
5
+
6
+ ---
7
+
8
+ date(シフトの日付)
9
+ start(開始時刻)
10
+ end(終了時刻)
11
+
12
+ これが、間違いの元。
13
+
14
+ シフトの日付は不要
15
+
16
+ datetime型で start, datetime型で end を持っていればすむことでは?