MySQL加入特定结果

时间:2015-01-12 21:21:18

标签: mysql join

我正在尝试构建一个查询以从表单构建器中提取数据,我只能在另一个字段值等于特定字段值的情况下才能加入字段值。我的查询没有返回任何行。

users
------------------
|id | name       |
------------------
|40 | John       |
|45 | Michael    |
|47 | Bob        |
------------------    

data_table
----------------------------------------------------
|id  | submission | field_type | field_value       |
----------------------------------------------------
|1   | 12345      | user       | 40                |
|2   | 12345      | score      | 5                 |
|3   | 12345      | completed  | 1                 |
|4   | 23456      | user       | 45                |
|5   | 23456      | score      | 3                 |
|6   | 23456      | completed  | 0                 |
|7   | 45678      | user       | 47                |
|8   | 45678      | score      | 2                 |
|9   | 45678      | completed  | 1                 |
----------------------------------------------------

Desired result

---------------
|Name | Score |
---------------
|John | 5     |
|Bob  | 2     |
---------------

Select 
    u.name,
    dt2.field_value as score
from
    users u
left join
    data_table dt on u.id=dt.field_value and dt.field_type='user'
left join
    data_table dt2 on dt.submission=dt2.submission and dt2.field_type='score'
where
    (dt.field_type='completed' and dt.field_value=1)

http://sqlfiddle.com/#!2/d6e72f/3

4 个答案:

答案 0 :(得分:1)

你可以做那样的事情(如果你真的无法改变你的数据结构,看起来很奇怪)。

你在data_table上有一个子查询,在该表上有两个自连接(因为你需要3个不同的条件和条件)

select u.name, s.score
from users u
join (
      select dt.field_value as user_id, dt1.field_value as score
      from data_table dt
      join data_table dt1 on dt1.submission = dt.submission
      join data_table dt2 on dt2.submission = dt1.submission
      where dt.field_type='user' and 
            dt1.field_type = 'score' and 
            dt2.field_type='completed' and 
            dt2.field_value = 1
      ) s
    on s.user_id = u.id

请参阅SqlFiddle

答案 1 :(得分:1)

工作小提琴http://sqlfiddle.com/#!2/d6e72f/19/0

当用户动态地向现有结构添加其他属性时,我已经看到了很多。您必须首先取消其他数据的删除,然后您可以将其视为普通表。由于mysql不支持unpivot,我使用了正常的工作。

Select u.name, score
from users u
INNER JOIN (
Select submission, 
   max(case when field_Type='user' then field_value end) as user,
   max(case when field_Type='score' then field_value end) as score,  
   max(case when field_Type='completed' then field_value end) as completed               
FROM data_table
group by submission) dt
  on dt.user = u.id
 and dt.completed = 1

这假设对于给定的提交,不能有多个field_Type值组合。如果有,这只会返回最大值。

基本上它的作用是将数据转换为表结构,然后我们可以联接回来。

我们执行max或min的原因是,对于给定的提交,我们返回一行而不是多行。同样,这简单地将数据展开并将行组合成一个。但是基于一个假设,即在提交中不会复制field_type和field_value。

答案 2 :(得分:1)

让我们来看看你实际在做什么,这样我们就可以看出出了什么问题:

Select 
    u.name,
    dt2.field_value as score
from
    users u 

获取用户列表

left join
    data_table dt on u.id=dt.field_value and dt.field_type='user'

仅加入“user”

类型的data_table中的行
left join
    data_table dt2 on dt.submission=dt2.submission and dt2.field_type='score'

仅加入“得分”类型的data_table中的行。 现在您的结果集看起来像:

用户,DT(类型为'USER'的数据表行),DT2(类型'SCORE'的数据表行)

where
    (dt.field_type='completed' and dt.field_value=1)

过滤结果以仅包含dt.field_type(之前已过滤为仅包含“user”类型)的用户具有“完整”类型的用户。

基本上你的联接会过滤掉'data_table'中的所有'完整'行,所以你的where语句找不到匹配项。这只是对正在发生的事情的解释。关于你的问题。

查看您的架构,您有几个选择。尽管我不是设计的粉丝,但我仍然可以编写您的查询:

SELECT U.name, SCORE_DT.field_value AS score
FROM user U
JOIN data_table DT ON DT.field_value=U.id AND DT.field_type="USER"
JOIN data_table SCORE_DT ON SCORE_DT.submission=DT.submission AND SCORE_DT.field_type="SCORE"
JOIN data_table COMPLETED_DT.submission=DT.submission AND COMPLETED_DT.field_type="COMPLETED" AND COMPLETED_DT.field_value=1

实际上,它会让你的生活更容易改变表设计,因为这个数据结构要求你构建查询,为你感兴趣的每一列执行数据透视操作。对于像这样的小数据集,它是可行的,但随着表单中列数的增加,使用它将变得非常繁琐。

答案 3 :(得分:1)

另一种有效的变体是......

select  x.name
    ,   d.field_value
from    data_table d
join    (select  u.name
             ,   d2.submission
         from    users       u
         join    data_table d2
                    on  d2.field_value = u.id 
                    and d2.field_type  = 'user'
         join   data_table  d3
                    on d2.submission = d3.submission
                    and d3.field_type = 'completed'
                    and d3.field_value = '1'
        ) x
          on x.submission = d.submission
          and d.field_type = 'score'

请参阅SqlFiddle

对于您的数据集,您可能会发现此或xQbert的答案以不同的方式执行。 我会试试看他们。根据您的数据,尝试获取最内部的查询以返回可能的最小数据集。例如,如果您知道只有一小部分data_table记录将具有'completed'='1',那么第三个嵌套选择可能不合理,如果它导致MySql使用的结果较小。