基于优先级的Case SQL查询

时间:2017-11-20 07:48:37

标签: mysql sql

我的用户表包含user_id和user_details等列。在user_details列中,它包含字符串格式的JSON数据,如下所示:

"[{"value":"sachin","label":"What's your first name?"},{"value":"test@example.com","label":"What's your email?"},{"value":"+911234567890","label":"What's your phone number?"},{"value":"xyz","label":"What's your city?"},{"value":"abc","label":"What's your address?"}]"

它将在user_details列中包含名称和值对中的数据,如上所示。

我想要一个sql查询来查找user_details列中的值,如果label包含“name”或“email”或“phone number”,则显示相应的值。 示例 - 1:

"[{"value":"sachin","label":"What's your first name?"},{"value":"test@example.com","label":"What's your email?"},{"value":"+911234567890","label":"What's your phone number?"},{"value":"xyz","label":"What's your city?"},{"value":"abc","label":"What's your address?"}]"

在此示例中,SQL查询应生成以下输出:

名称|萨钦

示例 - 2:

"[{"value":"test@example.com","label":"What's your email?"},{"value":"+911234567890","label":"What's your phone number?"},{"value":"xyz","label":"What's your city?"},{"value":"abc","label":"What's your address?"}]"

在这应该是: 电子邮件| test@example.com

示例 - 3:

"[{"value":"+911234567890","label":"What's your phone number?"},{"value":"xyz","label":"What's your city?"},{"value":"abc","label":"What's your address?"}]"

在这应该是: 电话| 911234567890

示例 - 4:

"[{"value":"xyz","label":"What's your city?"},{"value":"abc","label":"What's your address?"}]"

在这应该是: id |五 (在这个例子中,我们没有姓名,电子邮件或电话号码,然后查询应该返回id,即该行的主键。)

我尝试使用案例查询,但似乎没有用。有没有办法获得这个输出?

2 个答案:

答案 0 :(得分:1)

正如其他人所说,你真的应该改变你的数据库架构。但是,如果您仍然坚持使用当前设置,则此查询可能会满足您的需求:

SELECT
  CASE WHEN json_search(user_details, 'one', '%name%', null, '$[*].label')
         IS NOT NULL
       THEN 'name'
       WHEN json_search(user_details, 'one', '%email%', null, '$[*].label') 
         IS NOT NULL
       THEN 'email'
       WHEN json_search(user_details, 'one', '%phone number%', null, '$[*].label') 
         IS NOT NULL
       THEN 'phone'
       ELSE 'id'
  END type,
  CASE WHEN json_search(user_details, 'one', '%name%', null, '$[*].label') 
         IS NOT NULL
       THEN json_unquote(json_extract(user_details, 
              concat(
                json_unquote(
                  replace(
                    json_search(user_details, 'one', '%name%', null, '$[*].label'), 
                    '.label', '')),
                '.value')))
       WHEN json_search(user_details, 'one', '%email%', null, '$[*].label') 
         IS NOT NULL
       THEN json_unquote(json_extract(user_details, 
              concat(
                json_unquote(
                  replace(
                    json_search(user_details, 'one', '%email%', null, '$[*].label'), 
                    '.label', '')),
                '.value')))

       WHEN json_search(user_details, 'one', '%phone number%', null, '$[*].label') 
         IS NOT NULL
       THEN json_unquote(json_extract(user_details, 
              concat(
                json_unquote(
                  replace(
                    json_search(user_details, 'one', '%phone%', null, '$[*].label'), 
                    '.label', '')),
                '.value')))
       ELSE user_id
  END value
FROM json_user;      

答案 1 :(得分:0)

就个人而言,我不推荐这种表结构。数据库表需要保存一个特定的值,最好将电子邮件,电话号码等存储在自己的列中...从这个结构中读取数据会很复杂......但是,我确信你有充分的理由为了这。

如果你的user_details表中有键/值对,那么你可以根据标签给每个人一个优先级,这将是你的内部查询。然后从此内部查询中选择前1行:

select * from (
  select `value` as myvalue, `label` as mylabel, 1 as `priority` from user_details where `label` = 'What''s your first name?'
  union 
  select `value` as myvalue, `label` as mylabel, 2 as `priority` from user_details where `label` = 'What''s your email?'
  union 
  select `value` as myvalue, `label` as mylabel, 3 as `priority` from user_details where `label` = 'What''s your phone number?'
  union 
  select `id`    as myvalue, `label` as mylabel, 4 as `priority` from 
  user_details where `label` NOT IN ('What''s your first name?', 'What''s your email?', 'What''s your phone number?')
) as pri_table
order by priority
limit 1