MySQL:根据表名作为列值连接表

问题描述 投票:0回答:3

下面是我当前正在处理的数据库的数据库基础片段。

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

有可能吗..?

mysql join field
3个回答
0
投票

创建依赖于存储在另一个表中的表和字段名称的动态 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;

0
投票

对于固定数量的表,您可以像这样获得所需的结果。 请注意,索引不能很好地支持这种连接,因此会导致大表出现性能问题。

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);

在 DB Fiddle 上查看


0
投票

对于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 中循环结果集

© www.soinside.com 2019 - 2024. All rights reserved.