MySQL从4行、1列和9列中提取数据的正确方法是什么?
我已经研究并尝试了数天的SQL查询,以找到可以工作的“东西”。我有一个表apj32_facileforms_subrecords,它使用7列。我想显示的所有数据都在1列-“值”。“记录”显示条目的编号。“title”是我希望显示在标题行中的内容,但它不如“value”重要,因为“value”显示在基于“record”编号的一行中。 我尝试了很多CONCAT和各种Pivot查询,但似乎没有什么比“接近”我想要的最终结果更有效。 以下是表格的屏幕截图: 输出“应该”是线性的,因此一行包含9列: 项目Zipcode;名字;姓氏;地址;城市电话;电子邮件;(按那个顺序)交易。9列中的值来自“值”,因为它们与“记录”编号相关 我知道有很多类似的例子,但我发现没有一个例子能涵盖从“value”和CONCAT到1行的所有值 这可以获得我想要的所有数据-从MySQL从4行、1列和9列中提取数据的正确方法是什么?,mysql,rows,Mysql,Rows,我已经研究并尝试了数天的SQL查询,以找到可以工作的“东西”。我有一个表apj32_facileforms_subrecords,它使用7列。我想显示的所有数据都在1列-“值”。“记录”显示条目的编号。“title”是我希望显示在标题行中的内容,但它不如“value”重要,因为“value”显示在基于“record”编号的一行中。 我尝试了很多CONCAT和各种Pivot查询,但似乎没有什么比“接近”我想要的最终结果更有效。 以下是表格的屏幕截图: 输出“应该”是线性的,因此一行包含9列: 项
apj32\u facileforms\u子记录中选择record
,value
,其中(record
,value
)按record
顺序排列
但这些值仍在多行中。我可以使用该查询只获取值,但我仍然无法将它们放入一行。在这里的一位专家向我展示这是多么简单之前,我将继续玩这个查询,看看我是否能解决它。
如果有任何帮助,我们将不胜感激。使用SQL将EAV模型表示形式扁平化为关系表示形式可能会有些复杂,而且效率不高
两种常用的方法是条件聚合和选择列表中的相关子查询。这两种方法都需要对大型集合进行仔细的索引,以获得合适的性能
相关子查询示例
下面是一个相关子查询方法的示例,用于为某些记录获取“zipcode”属性的一个值
SELECT r.id
, ( SELECT v1.value
FROM `apj32_facileforms_subrecords` v1
WHERE v1.record = r.id
AND v1.name = 'zipcode'
ORDER BY v1.value LIMIT 0,1
) AS `Zipcode`
FROM ( SELECT 1 AS id ) r
扩展它,我们重复相关子查询,将属性标识符(“firstname”替换为“zipcode”。看起来我们还可以按元素引用它,例如v2.element=2
SELECT r.id
, ( SELECT v1.value
FROM `apj32_facileforms_subrecords` v1
WHERE v1.record = r.id
AND v1.name = 'zipcode'
ORDER BY v1.value LIMIT 0,1
) AS `Zipcode`
, ( SELECT v2.value
FROM `apj32_facileforms_subrecords` v2
WHERE v2.record = r.id
AND v2.name = 'firstname'
ORDER BY v2.value LIMIT 0,1
) AS `First Name`
, ( SELECT v3.value
FROM `apj32_facileforms_subrecords` v3
WHERE v3.record = r.id
AND v3.name = 'lastname'
ORDER BY v3.value LIMIT 0,1
) AS `Last Name`
FROM ( SELECT 1 AS id UNION ALL SELECT 2 ) r
返回类似于
id Zipcode First Name Last Name
-- ------- ---------- ---------
1 98228 David Bacon
2 98228 David Bacon
条件聚合方法示例
我们可以使用groupby
将多行折叠为每个实体的一行,并在表达式中使用条件测试通过聚合函数“挑选”属性值
SELECT r.id
, MIN(IF(v.name = 'zipcode' ,v.value,NULL)) AS `Zip Code`
, MIN(IF(v.name = 'firstname' ,v.value,NULL)) AS `First Name`
, MIN(IF(v.name = 'lastname' ,v.value,NULL)) AS `Last Name`
FROM ( SELECT 1 AS id UNION ALL SELECT 2 ) r
LEFT
JOIN `apj32_facileforms_subrecords` v
ON v.record = r.id
GROUP
BY r.id
对于更可移植的语法,我们可以用更多ANSI标准的CASE
表达式替换MySQLIF()
函数,例如
, MIN(CASE v.name WHEN 'zipcode' THEN v.value END) AS `Zip Code`
请注意,MySQL不支持SQL ServerPIVOT
语法,或OracleMODEL
语法,或PostgresCROSSTAB
或FILTER
语法
要将这两种方法中的任何一种扩展为动态的,要返回具有可变列数和多种列名的结果集…这在单个SQL语句的上下文中是不可能的。我们可以单独执行SQL语句来检索信息,这将允许我们动态地构造一个形式为sh的SQL语句下面,返回一组显式的列
上面概述的方法返回一个更传统的关系模型(每个列都有一个值)
非关系的将属性和值组合成单个字符串
如果我们有一些特殊的分隔符,我们可以使用GROUP_CONCAT函数将数据的表示形式组合在一起
作为一个初步的例子:
SELECT r.id
, GROUP_CONCAT(v.title,'=',v.value ORDER BY v.name) AS vals
FROM ( SELECT 1 AS id ) r
LEFT
JOIN `apj32_facileforms_subrecords` v
ON v.record = r.id
AND v.name in ('zipcode','firstname','lastname')
GROUP
BY r.id
返回两列,类似于
id vals
-- ---------------------------------------------------
1 First Name=David,Last Name=Bacon,Zip Code=98228
我们需要注意的是,从GROUP_CONCAT返回的值仅限于GROUP_CONCAT_max_len
字节。在这里,我们压缩了引出序号,将问题转移到稍后的处理中,以解析结果字符串。如果值中出现任何等号或逗号,将导致解析结果字符串的混乱因此,我们必须正确地避免出现在数据中的任何分隔符,这样GypH-CONTAT表达式将得到更多的参与。 StasOpFoad对于查询实体属性值模型有很多问题。建议您搜索“EAV枢轴查询”或“EAV水平查询”。.实现结果的两种常用方法是1)条件聚合和2)选择列表中的相关子查询。至于获取“所有值”,如果这意味着执行返回动态(变量)列数的SELECT语句。。。这在单个SQL SELECT语句中是不可能的。SELECT语句必须指定返回的列数和列名。这是否回答了您的问题?您是对的,我不相信SQL是将EAV模型解回到关系表示中的最佳工具。我发布的两种方法都是典型的,而且都是可行的。两者都需要合适的索引(使用EXPLAIN查看执行计划)。我的示例查询返回id
作为实体标识符的第一列,以防返回多个实体行。当然,可以返回其他表达式,我的示例中的内联视图通常会替换为对实体表的引用,以及限制实体行的WHERE子句……通过相关子查询方法,我们可以返回多值属性。考虑一个具有两个或多个值的实体,用于ZIPCODE。我们可以重复zipcode
子查询并将LIMIT 0,1更改为LIMIT 1,1以获得第二个值,再次重复LIMIT 2,1以获得第三个值。缺点是要构建的SQL要多得多。使用条件聚合方法,我们的SQL语法要少得多,只需引用一个values表