Mysql显示字段名称,其中值是特定的

时间:2017-11-06 14:40:16

标签: mysql

我有一张这样的表:

+------------------------+-------+------+-------+------+
| user                   | TELPE | CRS2 | MECAN | GOPI |
+------------------------+-------+------+-------+------+
| user1.foo@my-email.com | NULL  | NULL | 1     | NULL |
+------------------------+-------+------+-------+------+
| user2.foo@my-email.com | 1     | NULL | 1     | NULL |
+------------------------+-------+------+-------+------+

我很难找到返回值为1的特定用户的列名称的请求。

选择手动列不是一个选项,好像今天只有4列, 下周可能会有300人。

例如,搜索user1会得到以下结果:

+-------------+
| Books       |
+-------------+
| MECAN       |
+-------------+

和user2:

+-------------+
| Books       |
+-------------+
| TELPE       |
+-------------+
| MECAN       |
+-------------+

我的Mysql技能不是很高,所以感谢任何帮助,

非常感谢提前。

3 个答案:

答案 0 :(得分:1)

您需要将列转换为行,此过程称为unpivot。
你可以用UNIONS做到这一点。

<强>查询

 SELECT
     USER
   , TELPE AS 'column_value'
   , 'TELPE' AS 'column_source' 
  FROM 
   users 
  WHERE
   TELPE = 1 

  UNION ALL

  SELECT
     USER
   , CRS2 AS 'column_value'
   , 'CRS2' AS 'column_source'
  FROM 
   users
  WHERE
   CRS2 = 1    

  UNION ALL

  SELECT
     USER
   , MECAN AS 'column_value'
   , 'MECAN' AS 'column_source'
  FROM 
   users
  WHERE
   MECAN = 1 

  UNION ALL

  SELECT
     USER
   , GOPI AS 'column_value'
   , 'GOPI' AS 'column_source'
  FROM 
   users
  WHERE
   GOPI = 1 

<强>结果

user                    column_value  column_source  
----------------------  ------------  ---------------
user2.foo@my-email.com  1             TELPE          
user1.foo@my-email.com  1             MECAN          
user2.foo@my-email.com  1             MECAN          

现在,我们可以将此查询用作已交付的表格,以过滤所需的结果。

<强>查询

SELECT
 DISTINCT 
  column_source
FROM ( 

  SELECT
     USER
   , TELPE AS 'column_value'
   , 'TELPE' AS 'column_source' 
  FROM 
   users 
  WHERE
   TELPE = 1 

  UNION ALL

  SELECT
     USER
   , CRS2 AS 'column_value'
   , 'CRS2' AS 'column_source'
  FROM 
   users
  WHERE
    CRS2 = 1

  UNION ALL

  SELECT
     USER
   , MECAN AS 'column_value'
   , 'MECAN' AS 'column_source'
  FROM 
   users
  WHERE
   MECAN = 1 

  UNION ALL

  SELECT
     USER
   , GOPI AS 'column_value'
   , 'GOPI' AS 'column_source'
  FROM 
   users
  WHERE
   GOPI = 1 
) 
 AS
  users
WHERE
   users.user = 'user1.foo@my-email.com'
 AND
   users.column_value = 1

<强>结果

| column_source |
|---------------|
|         MECAN |

demo http://www.sqlfiddle.com/#!9/3ed091/19

<强> EDITED

  

手动选择列不是一个选项,好像今天只有4列,下周可能会有300列。

然后您需要转向动态SQL生成。

首先,当需要数字生成器时,此查询将生成从2到1001的1000个数字。 为什么我们需要一个数字生成器将在以后变得更加清晰。

<强>查询

SELECT 
  @row := @row + 1 AS number
FROM ( 
  SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
 AS row1
CROSS JOIN (
  SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) 
  AS row2
CROSS JOIN (
  SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) 
  AS row3            
CROSS JOIN (
 SELECT @row := 1
) 
 AS init_user_param 

<强>结果

   2
   3
   4
   5
   6
   7
   8
   9
  10
....
....
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001

现在我们需要一种方法来获取表用户的所有列。

<强>查询

  SELECT 
   GROUP_CONCAT(COLUMN_NAME) AS COLUMN_NAME
  FROM 
   information_schema.COLUMNS
  WHERE
     TABLE_NAME = 'users'
   AND
     TABLE_SCHEMA <> 'performance_schema'

<强>结果

COLUMN_NAME                 
----------------------------
user,TELPE,CRS2,MECAN,GOPI  

现在我们要生成一个像

这样的唯一列表
user  TELPE
user  CRS2
...
...
user  GOPI  

现在我们将数字生成器与查询结合起来以获取列。 我们还使用SUBSTRING_INDEX来溢出逗号分隔值。

<强>查询

SELECT
  DISTINCT
    SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', 1), ',', -1) column1
  , SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', generator.number), ',', -1) column2
FROM ( 

  SELECT 
   GROUP_CONCAT(COLUMN_NAME) AS COLUMN_NAME
  FROM 
   information_schema.COLUMNS
  WHERE
     TABLE_NAME = 'users'
   AND
     TABLE_SCHEMA <> 'performance_schema'
)
 AS user_column

CROSS JOIN (

    SELECT 
      @row := @row + 1 AS number
    FROM ( 
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
    )
     AS row1
    CROSS JOIN (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
    ) 
      AS row2
    CROSS JOIN (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
    ) 
      AS row3            
    CROSS JOIN (
     SELECT @row := 1
    ) 
     AS init_user_param  
)  
  AS generator

<强>结果

column1  column2  
-------  ---------
user     TELPE    
user     CRS2     
user     MECAN    
user     GOPI   

使SQL生成完全动态

<强>查询

SET @sql_union = NULL;

SELECT 
 GROUP_CONCAT(
   CONCAT(
    "
     SELECT
       ",column1,"
     , ",column2," AS 'column_value'
     , '",column2,"' AS 'column_source' 
     FROM 
       users 
      WHERE
       ",column2," = 1 
    " 
  )
  SEPARATOR 'UNION ALL'
 )
FROM ( 

  SELECT
    DISTINCT
      SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', 1), ',', -1) column1
    , SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', generator.number), ',', -1) column2
  FROM ( 

    SELECT 
     GROUP_CONCAT(COLUMN_NAME) AS COLUMN_NAME
    FROM 
     information_schema.COLUMNS
    WHERE
       TABLE_NAME = 'users'
    AND
      TABLE_SCHEMA <> 'performance_schema'
  )
   AS user_columns

  CROSS JOIN (

    SELECT 
      @row := @row + 1 AS number
    FROM ( 
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
    )
     AS row1
    CROSS JOIN (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
    ) 
      AS row2
    CROSS JOIN (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
    ) 
      AS row3            
    CROSS JOIN (
     SELECT @row := 1
    ) 
     AS init_user_param  
  )  
    AS generator
) 
 AS generator_union_sql INTO @sql_union;

SET @sql = CONCAT(
"
SELECT
 DISTINCT 
  column_source
FROM ( 
"
,@sql_union, 
"
) 
 AS
  users
WHERE
   users.user = 'user1.foo@my-email.com'
 AND
   users.column_value = 1
"
);

PREPARE queryUser FROM @sql;
EXECUTE queryUser;

<强>结果

column_source  
---------------
MECAN          

答案 1 :(得分:0)

我怀疑你正在寻找像

这样的东西
SELECT user, if(telpe=1,"TELPE","") as rTELPE, if(CRS2=1,"CRS2","") as rCRS2 from myTable

答案 2 :(得分:0)

我对你的问题的理解是:

SELECT 'TELPE' FROM yourTable WHERE telpe = 1 AND user = 'user1.foo@my-email.com'
UNION ALL
SELECT 'CRS2 ' FROM yourTable WHERE crs2 = 1 AND user = 'user1.foo@my-email.com'
UNION ALL
SELECT 'MECAN' FROM yourTable WHERE mecam = 1 AND user = 'user1.foo@my-email.com'
UNION ALL
SELECT 'GOPI' FROM yourTable WHERE gopi = 1 AND user = 'user1.foo@my-email.com'