回答編集履歴

2

lt\(\)未満 → lte\(\)以下

2017/06/09 06:12

投稿

dangao
dangao

スコア37

test CHANGED
@@ -34,7 +34,7 @@
34
34
 
35
35
  ->having([
36
36
 
37
- $query->newExpr()->lt($query->func()->count('Assigns.user_id'), $max, 'integer'),
37
+ $query->newExpr()->lte($query->func()->count('Assigns.user_id'), $max, 'integer'),
38
38
 
39
39
  $query->newExpr()->eq(
40
40
 

1

jobsテーブルをメインに取得するコードを追記

2017/06/09 06:12

投稿

dangao
dangao

スコア37

test CHANGED
@@ -1,3 +1,171 @@
1
+ mpywさん、詳しい回答ありがとうございます。
2
+
3
+ 私は今回の質問者ではありませんが、とてもためになりました。
4
+
5
+
6
+
7
+ 以下はjobsテーブルをメインに取得するCakePHP3のコードです。
8
+
9
+ 最後にページネーションを利用しています。
10
+
11
+ SQL・テーブル・データはmpywさんのものを拝借しています。
12
+
13
+
14
+
15
+ ```PHP
16
+
17
+ $user_id = 2;
18
+
19
+ $max = 3;
20
+
21
+
22
+
23
+ $query = $this->Jobs->find();
24
+
25
+ $query
26
+
27
+ ->leftJoinWith('Assigns')
28
+
29
+ ->group(
30
+
31
+ 'Jobs.id'
32
+
33
+ )
34
+
35
+ ->having([
36
+
37
+ $query->newExpr()->lt($query->func()->count('Assigns.user_id'), $max, 'integer'),
38
+
39
+ $query->newExpr()->eq(
40
+
41
+ $query->func()->coalesce([
42
+
43
+ $query->func()->sum(
44
+
45
+ $query->newExpr()->eq(
46
+
47
+ 'Assigns.user_id',
48
+
49
+ $user_id
50
+
51
+ )
52
+
53
+ ),
54
+
55
+ 0
56
+
57
+ ],
58
+
59
+ ['integer', 'integer']
60
+
61
+ ),
62
+
63
+ 0,
64
+
65
+ 'integer'
66
+
67
+ )
68
+
69
+ ]);
70
+
71
+
72
+
73
+ // 確認
74
+
75
+ debug($query->all());
76
+
77
+
78
+
79
+ // ページネーション
80
+
81
+ $this->set('jobs', $this->paginate($query));
82
+
83
+
84
+
85
+ ```
86
+
87
+
88
+
89
+ having句は長くなるので、以下のように書いてもいいと思います。
90
+
91
+ ```PHP
92
+
93
+ ->having([
94
+
95
+ 'COUNT(Assigns.user_id) <=' => $max,
96
+
97
+ "COALESCE(SUM(assigns.user_id = {$user_id}), 0) =" => 0
98
+
99
+ ]);
100
+
101
+ ```
102
+
103
+
104
+
105
+ CakePHP3のDebug Kitに表示されるSQL
106
+
107
+ ```SQL
108
+
109
+ SELECT
110
+
111
+ Jobs.id AS `Jobs__id`,
112
+
113
+ Jobs.name AS `Jobs__name`
114
+
115
+ FROM
116
+
117
+ jobs Jobs
118
+
119
+ LEFT JOIN assigns Assigns ON Jobs.id = (Assigns.job_id)
120
+
121
+ GROUP BY
122
+
123
+ Jobs.id
124
+
125
+ HAVING
126
+
127
+ (
128
+
129
+ (
130
+
131
+ COUNT(Assigns.user_id)
132
+
133
+ ) <= 3
134
+
135
+ AND (
136
+
137
+ COALESCE(
138
+
139
+ (
140
+
141
+ SUM(
142
+
143
+ (Assigns.user_id = 2)
144
+
145
+ )
146
+
147
+ ),
148
+
149
+ 0
150
+
151
+ )
152
+
153
+ ) = 0
154
+
155
+ )
156
+
157
+ ```
158
+
159
+
160
+
161
+ 以下のコードでは誤った値が取得されます。
162
+
163
+ ---
164
+
165
+ (履歴として残しておきますが間違いです。)
166
+
167
+
168
+
1
169
  mpywさんの作ったテーブルとデータを使って、ORMを使う方法を考えてみました。
2
170
 
3
171
  正攻法ではやり方が分からないので、jobsテーブルではなく、assignsテーブルをメインに使う方法です。