From 1ee2b4bd7938d5cf4cce0190563b32327aea1704 Mon Sep 17 00:00:00 2001 From: zhouyonggao <1971162852@qq.com> Date: Wed, 17 Dec 2025 18:21:30 +0800 Subject: [PATCH] =?UTF-8?q?refactor(exporter,=20schema):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96SQL=E6=9E=84=E5=BB=BA=E9=80=BB=E8=BE=91=E4=BB=A5?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除BuildSQL函数中的冗余去重逻辑,简化SQL构建过程 - 更新多个表的JOIN逻辑,使用ROW_NUMBER()函数确保每个订单只保留最新记录,避免1:N重复 - 提升代码可读性,确保SQL构建逻辑清晰明了 --- server/internal/exporter/sqlbuilder.go | 52 -------------------------- server/internal/schema/marketing.go | 14 +++---- server/internal/schema/ymt.go | 7 ++-- 3 files changed, 11 insertions(+), 62 deletions(-) diff --git a/server/internal/exporter/sqlbuilder.go b/server/internal/exporter/sqlbuilder.go index 0755494..f93c567 100644 --- a/server/internal/exporter/sqlbuilder.go +++ b/server/internal/exporter/sqlbuilder.go @@ -538,58 +538,6 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ sb.WriteString(" WHERE ") sb.WriteString(strings.Join(where, " AND ")) } - needDedupe := false - if req.Datasource == "marketing" && req.MainTable == "order" && (need["order_voucher"] || need["voucher"] || need["voucher_batch"] || need["key_batch"] || need["code_batch"]) { - needDedupe = true - } - if req.Datasource == "ymt" && (req.MainTable == "order" || req.MainTable == "order_info") && (need["order_digit"] || need["order_voucher"] || need["voucher"] || need["voucher_batch"]) { - needDedupe = true - } - if needDedupe { - // Extract alias names in order - aliases := make([]string, 0, len(cols)) - sources := make([]string, 0, len(cols)) - for _, c := range cols { - pos := strings.LastIndex(c, " AS `") - if pos < 0 { - continue - } - alias := c[pos+5:] - if len(alias) == 0 { - continue - } - if alias[len(alias)-1] == '`' { - alias = alias[:len(alias)-1] - } - aliases = append(aliases, alias) - parts := strings.Split(alias, ".") - src := "" - if len(parts) >= 1 { - src = parts[0] - } - sources = append(sources, src) - } - // 聚合时按别名分组:主表字段别名始终是 req.MainTable.order_number - pkAlias := req.MainTable + ".order_number" - var out strings.Builder - out.WriteString("SELECT ") - for i := range aliases { - if i > 0 { - out.WriteString(",") - } - alias := aliases[i] - src := sources[i] - if src == "order" { - out.WriteString("sub.`" + alias + "`") - } else { - out.WriteString("MIN(sub.`" + alias + "`) AS `" + alias + "`") - } - } - out.WriteString(" FROM (") - out.WriteString(sb.String()) - out.WriteString(") AS sub GROUP BY sub.`" + pkAlias + "`") - return out.String(), args, nil - } return sb.String(), args, nil } diff --git a/server/internal/schema/marketing.go b/server/internal/schema/marketing.go index b160038..3e22f72 100644 --- a/server/internal/schema/marketing.go +++ b/server/internal/schema/marketing.go @@ -12,28 +12,28 @@ func (marketingSchema) BuildJoins(need map[string]bool, main string) []string { out = append(out, " LEFT JOIN `order_detail` ON `order_detail`.order_number = `order`.order_number") } if need["order_cash"] { - out = append(out, " LEFT JOIN `order_cash` ON `order_cash`.order_number = `order`.order_number") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `order_cash`.*, ROW_NUMBER() OVER (PARTITION BY `order_cash`.order_number ORDER BY `order_cash`.id DESC) AS rn FROM `order_cash`) t WHERE t.rn = 1) AS `order_cash` ON `order_cash`.order_number = `order`.order_number") } if need["order_voucher"] { - out = append(out, " LEFT JOIN `order_voucher` ON `order_voucher`.order_number = `order`.order_number") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `order_voucher`.*, ROW_NUMBER() OVER (PARTITION BY `order_voucher`.order_number ORDER BY `order_voucher`.id DESC) AS rn FROM `order_voucher`) t WHERE t.rn = 1) AS `order_voucher` ON `order_voucher`.order_number = `order`.order_number") } if need["plan"] || need["key_batch"] { out = append(out, " LEFT JOIN `plan` ON `plan`.id = `order`.plan_id") } if need["key_batch"] { - out = append(out, " LEFT JOIN `key_batch` ON `key_batch`.plan_id = `plan`.id") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `key_batch`.*, ROW_NUMBER() OVER (PARTITION BY `key_batch`.plan_id ORDER BY `key_batch`.id DESC) AS rn FROM `key_batch`) t WHERE t.rn = 1) AS `key_batch` ON `key_batch`.plan_id = `plan`.id") } if need["code_batch"] { - out = append(out, " LEFT JOIN `code_batch` ON `code_batch`.key_batch_id = `key_batch`.id") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `code_batch`.*, ROW_NUMBER() OVER (PARTITION BY `code_batch`.key_batch_id ORDER BY `code_batch`.id DESC) AS rn FROM `code_batch`) t WHERE t.rn = 1) AS `code_batch` ON `code_batch`.key_batch_id = `key_batch`.id") } if need["voucher"] { - out = append(out, " LEFT JOIN `voucher` ON `voucher`.channel_activity_id = `order_voucher`.channel_activity_id") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `voucher`.*, ROW_NUMBER() OVER (PARTITION BY `voucher`.channel_activity_id ORDER BY `voucher`.id DESC) AS rn FROM `voucher`) t WHERE t.rn = 1) AS `voucher` ON `voucher`.channel_activity_id = `order_voucher`.channel_activity_id") } if need["voucher_batch"] { - out = append(out, " LEFT JOIN `voucher_batch` ON `voucher_batch`.voucher_id = `voucher`.id") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `voucher_batch`.*, ROW_NUMBER() OVER (PARTITION BY `voucher_batch`.voucher_id ORDER BY `voucher_batch`.id DESC) AS rn FROM `voucher_batch`) t WHERE t.rn = 1) AS `voucher_batch` ON `voucher_batch`.voucher_id = `voucher`.id") } if need["merchant_key_send"] { - out = append(out, " LEFT JOIN `merchant_key_send` ON `order`.`key` = `merchant_key_send`.key") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `merchant_key_send`.*, ROW_NUMBER() OVER (PARTITION BY `merchant_key_send`.key ORDER BY `merchant_key_send`.id DESC) AS rn FROM `merchant_key_send`) t WHERE t.rn = 1) AS `merchant_key_send` ON `order`.`key` = `merchant_key_send`.key") } return out } diff --git a/server/internal/schema/ymt.go b/server/internal/schema/ymt.go index 07687e2..c628116 100644 --- a/server/internal/schema/ymt.go +++ b/server/internal/schema/ymt.go @@ -52,13 +52,14 @@ func (s ymtSchema) MapField(t, f string) (string, bool) { func (s ymtSchema) BuildJoins(need map[string]bool, main string) []string { out := []string{} if need["order_cash"] { - out = append(out, " LEFT JOIN `order_cash` ON `order_cash`.order_no = `order_info`.order_no") + // avoid 1:N duplication: keep latest row per order_no (no GROUP BY) + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `order_cash`.*, ROW_NUMBER() OVER (PARTITION BY `order_cash`.order_no ORDER BY `order_cash`.id DESC) AS rn FROM `order_cash`) t WHERE t.rn = 1) AS `order_cash` ON `order_cash`.order_no = `order_info`.order_no") } if need["order_voucher"] { - out = append(out, " LEFT JOIN `order_voucher` ON `order_voucher`.order_no = `order_info`.order_no") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `order_voucher`.*, ROW_NUMBER() OVER (PARTITION BY `order_voucher`.order_no ORDER BY `order_voucher`.id DESC) AS rn FROM `order_voucher`) t WHERE t.rn = 1) AS `order_voucher` ON `order_voucher`.order_no = `order_info`.order_no") } if need["order_digit"] { - out = append(out, " LEFT JOIN `order_digit` ON `order_digit`.order_no = `order_info`.order_no") + out = append(out, " LEFT JOIN (SELECT * FROM (SELECT `order_digit`.*, ROW_NUMBER() OVER (PARTITION BY `order_digit`.order_no ORDER BY `order_digit`.id DESC) AS rn FROM `order_digit`) t WHERE t.rn = 1) AS `order_digit` ON `order_digit`.order_no = `order_info`.order_no") } if need["goods_voucher_batch"] { out = append(out, " LEFT JOIN `goods_voucher_batch` ON `goods_voucher_batch`.channel_batch_no = `order_voucher`.channel_batch_no")