创建会员开单耗卡项目数视图.sql
8.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
-- ============================================
-- 创建会员开单耗卡项目数视图
-- ============================================
-- 说明:创建视图可以提升查询效率,避免每次都执行复杂的JOIN和聚合操作
-- 视图会预先聚合好数据,查询时直接使用
-- ============================================
-- 方案1:基础聚合视图(推荐)
-- ============================================
-- 优点:查询简单、性能好、可以灵活按时间范围查询
-- 缺点:仍然需要每次查询时过滤时间范围
-- 删除已存在的视图(如果存在)
DROP VIEW IF EXISTS v_member_billing_consume_project;
-- 创建视图:会员开单项目数汇总(不限制时间,包含所有数据)
CREATE VIEW v_member_billing_project AS
SELECT
px.F_MemberId as member_id,
kd.djmd as store_id,
kd.kdrq as billing_date,
SUM(CAST(px.F_ProjectNumber AS DECIMAL(18,2))) as billing_project_count
FROM lq_kd_pxmx px
INNER JOIN lq_kd_kdjlb kd ON px.glkdbh = kd.F_Id
WHERE px.F_IsEffective = 1
AND kd.F_IsEffective = 1
AND px.F_MemberId IS NOT NULL
AND px.F_MemberId != ''
GROUP BY px.F_MemberId, kd.djmd, DATE(kd.kdrq);
-- 创建视图:会员耗卡项目数汇总(不限制时间,包含所有数据)
CREATE VIEW v_member_consume_project AS
SELECT
xhpx.F_MemberId as member_id,
xh.md as store_id,
xh.hksj as consume_date,
SUM(CAST(xhpx.F_ProjectNumber AS DECIMAL(18,2))) as consume_project_count
FROM lq_xh_pxmx xhpx
INNER JOIN lq_xh_hyhk xh ON xhpx.F_ConsumeInfoId = xh.F_Id
WHERE xhpx.F_IsEffective = 1
AND xh.F_IsEffective = 1
AND xhpx.F_MemberId IS NOT NULL
AND xhpx.F_MemberId != ''
GROUP BY xhpx.F_MemberId, xh.md, DATE(xh.hksj);
-- 创建组合视图:会员开单耗卡项目数(按日汇总)
CREATE VIEW v_member_billing_consume_daily AS
SELECT
COALESCE(billing.member_id, consume.member_id) as member_id,
COALESCE(billing.store_id, consume.store_id) as store_id,
COALESCE(billing.billing_date, consume.consume_date) as statistics_date,
COALESCE(billing.billing_project_count, 0) as billing_project_count,
COALESCE(consume.consume_project_count, 0) as consume_project_count,
(COALESCE(billing.billing_project_count, 0) - COALESCE(consume.consume_project_count, 0)) as remaining_project_count
FROM v_member_billing_project billing
FULL OUTER JOIN v_member_consume_project consume
ON billing.member_id = consume.member_id
AND billing.store_id = consume.store_id
AND DATE(billing.billing_date) = DATE(consume.consume_date);
-- ============================================
-- 方案2:使用UNION ALL的视图(兼容MySQL,推荐)
-- ============================================
-- 优点:兼容MySQL所有版本、查询简单、性能好
DROP VIEW IF EXISTS v_member_billing_consume_project;
CREATE VIEW v_member_billing_consume_project AS
SELECT
member_id,
store_id,
statistics_date,
SUM(billing_project_count) as billing_project_count,
SUM(consume_project_count) as consume_project_count,
SUM(billing_project_count) - SUM(consume_project_count) as remaining_project_count
FROM (
-- 开单项目数(按会员、门店、日期分组)
SELECT
px.F_MemberId as member_id,
kd.djmd as store_id,
DATE(kd.kdrq) as statistics_date,
SUM(CAST(px.F_ProjectNumber AS DECIMAL(18,2))) as billing_project_count,
0 as consume_project_count
FROM lq_kd_pxmx px
INNER JOIN lq_kd_kdjlb kd ON px.glkdbh = kd.F_Id
WHERE px.F_IsEffective = 1
AND kd.F_IsEffective = 1
AND px.F_MemberId IS NOT NULL
AND px.F_MemberId != ''
GROUP BY px.F_MemberId, kd.djmd, DATE(kd.kdrq)
UNION ALL
-- 耗卡项目数(按会员、门店、日期分组)
SELECT
xhpx.F_MemberId as member_id,
xh.md as store_id,
DATE(xh.hksj) as statistics_date,
0 as billing_project_count,
SUM(CAST(xhpx.F_ProjectNumber AS DECIMAL(18,2))) as consume_project_count
FROM lq_xh_pxmx xhpx
INNER JOIN lq_xh_hyhk xh ON xhpx.F_ConsumeInfoId = xh.F_Id
WHERE xhpx.F_IsEffective = 1
AND xh.F_IsEffective = 1
AND xhpx.F_MemberId IS NOT NULL
AND xhpx.F_MemberId != ''
GROUP BY xhpx.F_MemberId, xh.md, DATE(xh.hksj)
) all_data
GROUP BY member_id, store_id, statistics_date;
-- ============================================
-- 方案3:按会员汇总的总视图(不按日期,累计汇总)
-- ============================================
-- 优点:查询最简单、性能最好(适合查询总量)
-- 缺点:无法按时间范围查询
DROP VIEW IF EXISTS v_member_billing_consume_total;
CREATE VIEW v_member_billing_consume_total AS
SELECT
member_id,
SUM(billing_project_count) as total_billing_project_count,
SUM(consume_project_count) as total_consume_project_count,
SUM(billing_project_count) - SUM(consume_project_count) as total_remaining_project_count,
COUNT(DISTINCT store_id) as store_count
FROM (
-- 开单项目数(按会员、门店汇总)
SELECT
px.F_MemberId as member_id,
kd.djmd as store_id,
SUM(CAST(px.F_ProjectNumber AS DECIMAL(18,2))) as billing_project_count,
0 as consume_project_count
FROM lq_kd_pxmx px
INNER JOIN lq_kd_kdjlb kd ON px.glkdbh = kd.F_Id
WHERE px.F_IsEffective = 1
AND kd.F_IsEffective = 1
AND px.F_MemberId IS NOT NULL
AND px.F_MemberId != ''
GROUP BY px.F_MemberId, kd.djmd
UNION ALL
-- 耗卡项目数(按会员、门店汇总)
SELECT
xhpx.F_MemberId as member_id,
xh.md as store_id,
0 as billing_project_count,
SUM(CAST(xhpx.F_ProjectNumber AS DECIMAL(18,2))) as consume_project_count
FROM lq_xh_pxmx xhpx
INNER JOIN lq_xh_hyhk xh ON xhpx.F_ConsumeInfoId = xh.F_Id
WHERE xhpx.F_IsEffective = 1
AND xh.F_IsEffective = 1
AND xhpx.F_MemberId IS NOT NULL
AND xhpx.F_MemberId != ''
GROUP BY xhpx.F_MemberId, xh.md
) all_data
GROUP BY member_id;
-- ============================================
-- 使用视图的查询示例
-- ============================================
-- 示例1:查询所有会员的开单耗卡项目数(按会员汇总,不限制时间)
SELECT
member_id,
SUM(billing_project_count) as billing_project_count,
SUM(consume_project_count) as consume_project_count,
SUM(remaining_project_count) as remaining_project_count
FROM v_member_billing_consume_project
GROUP BY member_id
ORDER BY billing_project_count DESC;
-- 示例2:查询指定时间范围内的数据
SELECT
member_id,
SUM(billing_project_count) as billing_project_count,
SUM(consume_project_count) as consume_project_count,
SUM(remaining_project_count) as remaining_project_count
FROM v_member_billing_consume_project
WHERE statistics_date >= '2025-10-01'
AND statistics_date <= '2025-10-30'
GROUP BY member_id
ORDER BY billing_project_count DESC;
-- 示例3:查询指定门店的数据
SELECT
member_id,
SUM(billing_project_count) as billing_project_count,
SUM(consume_project_count) as consume_project_count,
SUM(remaining_project_count) as remaining_project_count
FROM v_member_billing_consume_project
WHERE store_id = '1649328471923847169'
AND statistics_date >= '2025-10-01'
AND statistics_date <= '2025-10-30'
GROUP BY member_id
ORDER BY billing_project_count DESC;
-- 示例4:使用总视图(最简单的查询,累计所有数据)
SELECT
member_id,
total_billing_project_count,
total_consume_project_count,
total_remaining_project_count,
store_count
FROM v_member_billing_consume_total
ORDER BY total_billing_project_count DESC
LIMIT 100;
-- ============================================
-- 视图性能优化建议
-- ============================================
-- 1. 确保基础表已创建索引(参考优化GetStoreRemainingRights性能索引.sql)
-- 2. 如果数据量很大,可以考虑:
-- a. 创建物化视图(但MySQL不支持,需要定期刷新汇总表)
-- b. 创建汇总表,定期更新(推荐)
-- 3. 定期分析视图性能:
-- EXPLAIN SELECT * FROM v_member_billing_consume_project WHERE statistics_date >= '2025-10-01';
-- ============================================
-- 视图维护
-- ============================================
-- 查看视图定义
-- SHOW CREATE VIEW v_member_billing_consume_project;
-- 查看所有视图
-- SELECT TABLE_NAME
-- FROM INFORMATION_SCHEMA.VIEWS
-- WHERE TABLE_SCHEMA = DATABASE();
-- 删除视图
-- DROP VIEW IF EXISTS v_member_billing_consume_project;
-- DROP VIEW IF EXISTS v_member_billing_consume_total;