我正在尝试构建一个查询以从表单构建器中提取数据,我只能在另一个字段值等于特定字段值的情况下才能加入字段值。我的查询没有返回任何行。
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)
答案 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使用的结果较小。