下面是我当前正在处理的数据库的数据库基础片段。
表
transactions
:
id | 参考表 | 参考字段 | reference_id | 创建于 |
---|---|---|---|---|
1 | 在线充值 | online_recharge_id | 10 | 2024-01-31 |
2 | 在线充值 | online_recharge_id | 11 | 2024-03-03 |
3 | 钱包_扣款 | wallet_deduction_id | 10 | 2024-02-01 |
... | ... | ... | ... |
表
online_recharges
:
online_recharge_id | 备注 | 金额 | ... |
---|---|---|---|
10 | 1月1日在线充值 | 100 | ... |
11 | 3月3日线上充值 | 150 | ... |
表
wallet_deductions
:
wllet_deduction_id | 备注 | 金额 | ... |
---|---|---|---|
10 | 2月1日扣钱包 | 20 | ... |
我需要根据
transactions.reference_table
的值连接表格。像这样的东西:
SELECT T.reference_table, ref.remarks, ref.amount, T.created_at FROM transactions AS T
LEFT JOIN T.reference_table AS ref ON ref.reference_field = T.reference_id
ORDER BY T.created_at DESC
有可能吗..?
创建依赖于存储在另一个表中的表和字段名称的动态 SQL 连接在 SQL 中提出了复杂且非标准的挑战。标准 SQL 查询本身并不支持 JOIN 子句或其他查询段中的动态表或列名称,因为执行计划需要静态详细信息进行编译和优化。尽管如此,还是有一些替代技术和解决方法可以用来获得相同的结果。您可以使用条件连接:
SELECT
T.reference_table,
CASE
WHEN T.reference_table = 'online_recharges' THEN Recharge.remarks
WHEN T.reference_table = 'wallet_deductions' THEN Deduction.remarks
END AS remarks,
CASE
WHEN T.reference_table = 'online_recharges' THEN Recharge.amount
WHEN T.reference_table = 'wallet_deductions' THEN Deduction.amount
END AS amount,
T.created_at
FROM
transactions AS T
LEFT JOIN
online_recharges AS Recharge ON T.reference_table = 'online_recharges' AND Recharge.online_recharge_id = T.reference_id
LEFT JOIN
wallet_deductions AS Deduction ON T.reference_table = 'wallet_deductions' AND Deduction.wallet_deduction_id = T.reference_id
ORDER BY
T.created_at DESC
LIMIT 25;
对于固定数量的表,您可以像这样获得所需的结果。 请注意,索引不能很好地支持这种连接,因此会导致大表出现性能问题。
select *
from transactions t join
(
select 'online_recharges' as src, online_recharge_id as id, remarks, amount
from online_recharges
union all
select 'wallet_deductions' as src, wallet_deduction_id as id, remarks, amount
from wallet_deductions
) rac
on t.reference_table = rac.src
and t.reference_id = rac.id;
id | 参考表 | 参考字段 | reference_id | 来源 | id | 备注 | 金额 |
---|---|---|---|---|---|---|---|
1 | 在线充值 | online_recharge_id | 10 | 在线充值 | 10 | 1月1日在线充值 | 100 |
2 | 在线充值 | online_recharge_id | 11 | 在线充值 | 11 | 3月3日线上充值 | 150 |
3 | 钱包_扣款 | wallet_deduction_id | 10 | 钱包_扣款 | 10 | 2月1日扣钱包 | 20 |
架构(MySQL v8.0)
create table transactions
(
id integer,
reference_table varchar(30),
reference_field varchar(30),
reference_id integer
);
create table online_recharges
(
online_recharge_id integer,
remarks varchar(200),
amount integer
);
create table wallet_deductions
(
wallet_deduction_id integer,
remarks varchar(200),
amount integer
);
insert into transactions values
(1, 'online_recharges','online_recharge_id', 10),
(2, 'online_recharges','online_recharge_id', 11),
(3, 'wallet_deductions', 'wallet_deduction_id', 10);
insert into online_recharges values
(10, 'online recharge on 1st January', 100),
(11, 'online recharge on 3rd March', 150);
insert into wallet_deductions values
(10, 'wallet deduction on 1st February', 20);
对于nne行事务,您可以使用动态sql
SELECT
CONCAT('SELECT "', reference_table,'", ref.remarks, ref.amount,"', t.created_at,
'" FROM ', reference_table, ' as ref WHERE ' ,reference_field, ' = ?'), reference_id
INTO @sql,@id
FROM transactions t
WHERE id = 1;
SELECT @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt USING @id;
DROP PREPARE stmt;
@sql |
---|
从 online_recharges 中选择“online_recharges”、ref.remarks、ref.amount、“2024-05-08”作为参考 WHERE online_recharge_id = ? |
Statement prepared
在线充值 | 备注 | 金额 | 2024-05-08 |
---|---|---|---|
在线充值 | 1月1日在线充值 | 100 | 2024-05-08 |
如果您想要不止一行,您需要循环遍历您需要的事务中的所有行,并单独运行每一行,然后并集到一个 temporqay 表,就像这里描述的过程在 MySQL 中循环结果集