具有动态列名的SQL SELECT语句

时间:2019-10-02 21:08:07

标签: mysql sql select

我尝试选择名称为其他列内容的列。我正在使用MySQL 5.6。

假设我有“ table1”:

+------+------------+------------+---------------+---------------+
|  id  |  val_int1  |  val_int2  |  val_string1  |  val_string2  |
+------+------------+------------+---------------+---------------+
|  1   |  70        |  88        |  xxx          |  yyy          |
+------+------------+------------+---------------+---------------+

和“ table2”:

+------+--------+----------+
|  id  |  type  |  ref_id  |
+------+--------+----------+
|  10  |  i1    |  1       |
|  20  |  s2    |  1       |
+------+--------+----------+

我想要做的是:将table1和table2连接起来,table2.type字段包含要选择的table1中列的名称。还有一个问题,类型字段仅包含我必须扩展的缩写。
这将在以下SQL语句中结束:

SELECT
    t1.id,
    IF(t2.type REGEXP 'i[0-9]+', REPLACE(t2.type, 'i', 'val_int'), REPLACE(t2.type, 's', 'val_string'))
FROM
    table1 t1, table2 t2
WHERE
    t1.id = t2.ref_id AND t1.id = 1

结果是REPLACE函数将val_int1和val_string2作为固定字符串返回,而不将其作为列名进行处理。

我真正期望的是:

+-----+-------+
|  1  |  70   |
|  1  |  yyy  |
+-----+-------+

2 个答案:

答案 0 :(得分:5)

您需要某种case表达式:

select t1.id,
       (case when t2.type = 'i1' then cast(val_int_1 as varchar(255))
             when t2.type = 'i2' then cast(val_int_2 as varchar(255))
             when t2.type = 's1' then val_string_1
             when t2.type = 's2' then val_string_2
        end) as val
from table1 t1 cross join
     table2 t2;

您可能会抱怨“哦,我有那么多专栏”。基本上太糟糕了。您的数据库设计不佳。您正在尝试对字符串和列名进行部分匹配。甚至动态SQL解决方案也不是很可行。

答案 1 :(得分:0)

使用大小写表达式,这就是我要解决的方式:

DECLARE @table1 TABLE
(
    id INT,
    val_int1 INT,
    val_int2 INT,
    val_string1 NVARCHAR(100),
    val_string2 NVARCHAR(100)
)

INSERT INTO @table1 VALUES
(1,70,88,'xxx','yyy')

DECLARE @table2 TABLE
(
    id INT,
    type NVARCHAR(MAX),
    ref_id INT
)

INSERT INTO @table2 VALUES
(10,'i1',1),
(20,'s2',1)

SELECT 
    id,
    CASE WHEN type = 'i1' THEN CAST((SELECT TOP 1 val_int1 FROM @table1) AS NVARCHAR(100)) ELSE 
        CASE WHEN type = 'i2' THEN CAST((SELECT TOP 1 val_int2 FROM @table1) AS NVARCHAR(100)) ELSE 
        CASE WHEN type = 's1' THEN (SELECT TOP 1 val_string1 FROM @table1) ELSE 
            (SELECT TOP 1 val_string2 FROM @table1) END END END
FROM @table2 t2

输出:

10  70
20  yyy