根据存储在另一个表中的列名选择列

时间:2018-11-13 10:57:03

标签: mysql sql

我试图从另一个表(UserTable)中获取一个单元格值,在该表中已在原始表(DataTable)中指定了该单元格的列。单元格值将用于计算得分,然后确定查询结果的顺序。

UserTable:
+--------+------+------+------+
| userid | c1   | c2   | c3   |
+--------+------+------+------+
|    id1 |    0 |    1 |    1 |
|    id2 |    0 |    0 |    1 |
|    id3 |    1 |    0 |    0 |
|    id4 |    1 |    1 |    0 |
+--------+------+------+------+

DataTable:
+--------+------+------+------+
| id     | ColA | ColB | ColC |
+--------+------+------+------+
|      1 | A    | B    | c1   |
|      2 | D    | E    | c3   |
|      3 | G    | H    | c2   |
|      4 | J    | K    | c3   |
+--------+------+------+------+

我当前无法使用的查询是:

SELECT *, 
       (SELECT DataTable.ColC 
        FROM UserTable 
        WHERE UserTable.userid = 'some_user_id') AS score 
FROM DataTable 
ORDER BY score DESC

但这不会在UserTable中选择适当的列,而是返回ColC中包含的字符串值。

预期输出: 例如,如果“ some_user_id”设置为“ id2”。预期的输出将是:

+--------+------+------+------+------+
| id     | ColA | ColB | ColC | score|
+--------+------+------+------+------+
|      2 | D    | E    | c3   |  1   |
|      4 | J    | K    | c3   |  1   |
|      1 | A    | B    | c1   |  0   |
|      3 | G    | H    | c2   |  0   |
+--------+------+------+------+------+

其中的score列只是从UserTable中查找值。

有可能解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

您不能动态地执行此操作。但是您可以构建一个CASE语句,将列名映射到列:

SELECT DataTable.*, (
    SELECT CASE DataTable.ColC
        WHEN 'c1' THEN UserTable.c1
        WHEN 'c2' THEN UserTable.c3
        WHEN 'c3' THEN UserTable.c3
    END
    FROM UserTable
    WHERE UserTable.userid = 'id2'
) AS score
FROM DataTable
ORDER BY score DESC

答案 1 :(得分:0)

Declare @expr nvarchar(max);  
Declare @value nvarchar(max);   
DECLARE db_cursor CURSOR  
FOR Select colC from dbo.DataTable;

OPEN db_cursor;  
FETCH NEXT FROM db_cursor INTO @value;  
Set @expr = 'Select ' + @value;  
WHILE @@FETCH_STATUS = 0  
BEGIN  
       Set @expr += ',' + @value  
       FETCH NEXT FROM db_cursor INTO @value;  
END;  
CLOSE db_cursor;  
DEALLOCATE db_cursor;  

EXEC (@expr + ' from dbo.UserTable')

答案 2 :(得分:0)

我喜欢通过取消用户表来表达这一点:

select dt.*, uts.score
from datatable dt left join
     ((select ut.userid, 'c1' as which, c1 as score
       from usertable ut
      ) union all
      (select ut.userid, 'c2' as which, c2 as score
       from usertable ut
      ) union all
      (select ut.userid, 'c3' as which, c3 as score
       from usertable ut
      ) 
     ) uts
     on dt.colc = uts.which 
where uts.userid = ?;

我之所以喜欢这种方法,是因为子查询会建议您真正需要的表。您不应在列中存储不同的得分值。您应该有一个userScores表,每个用户和每个分数都有一行。