2015-01-12 98 views
0

我想构建一个查询来从表单生成器中提取数据,我可以只在其他字段值等于特定值时在字段值上加入数据。我的查询返回没有行。MySQL加入特定结果

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

+1

你在问不可能的条件。你加入'dt.field_type ='user'',所以'dt'中的**只有**记录可以用于'where'过滤是'user'记录。将不会有任何'完成'记录... –

回答

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

+0

谢谢拉斐尔我会检查这一点 - 我不能改变结构,它看起来很奇怪,但它是一个系统,允许用户从头开始构建表单并存储在MySQL中的内容,然后访问数据的报告等等。在这两个表中有更多的字段,但它们并不真正相关,所以我把它们排除在外 – bhttoan

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在提交中不会重复。

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' 

从data_table类型的加入只是行“用户'

left join 
    data_table dt2 on dt.submission=dt2.submission and dt2.field_type='score' 

仅加入类型为'score'的data_table中的行。 现在你的结果集看起来像:

用户,DT(数据表行类型“用户”),DT2(数据表行类型“SCORE”)

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

筛选的结果,包括只有dt.field_type(以前被过滤为仅包含类型“用户”)的用户的类型为“完成”。

基本上你的连接过滤掉'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 

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

+0

谢谢你解释我出错的地方 – bhttoan

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',则第三个嵌套select可能不会不合理,如果它导致MySql使用较小的结果。