我需要创建一个表结果(并找出是否可能在MySQL的约束内),将包含来自2个表的数据,但查询本身将基于3个表(包括一个连接表)。并将合并的结果添加到输出结果中。
表结构:registrants
id, first name, last name, industryID
industries
id, name
registrants_industries (join table)
id, registrant_id, industry_id
因此,在最终输出结果表中,任何注册者都可以有0个、1个或多个行业,这些行业名称应该添加到最终结果表的末尾。
registrants.id,
registrants.first_name,
registrants.last_name,
industry.name-1,
industry.name-2,
industry.name-3,
industry.name-4,
industry.name-5.
但是所有的列应该按行业对齐。例如,如果有5个行业,输出将如下所示:
(行业排序:油漆,瓷砖,一般建筑,庭院护理,屋顶)
354, Mike, Smith, Painting,’’,’’,Yard Care,’’
599, Joe, Jones, ‘’,’’,’General Construction’,’’,’’
所以所有的行业列将对齐,并可以在Excel中排序等。
这个查询输出与(我的)SQL可能吗?如果是的话,你能就最好的方法提出什么好的建议吗?
我开始写我的查询,只是发现没有答案来解决我添加的基于匹配的列。然后按行排列
您可以使用group_concat将所有行业放在一列中。我知道这不是你问题的确切答案,但它很接近,我不相信你问的只有3个连接是可能的。
SELECT
R.id,
R.first_name,
R.last_name,
GROUP_CONCAT(I.name) AS industries
FROM registrants R
JOIN registrants_industries RI ON R.id = RI.registrant_id
JOIN industires I ON RI.industry_id = I.id
GROUP BY R.id
这将产生
354, Mike, Smith, "Painting,Yard Care"
599, Joe, Jones, "’General Construction’"
您可以使用子查询为每个registrants_industries
条目分配一个数字:
select r.id,
, r.first_name
, r.last_name
, min(case when ri.RowNr = 1 then i.name end) as [Industry-1]
, min(case when ri.RowNr = 2 then i.name end) as [Industry-2]
, min(case when ri.RowNr = 3 then i.name end) as [Industry-3]
, min(case when ri.RowNr = 4 then i.name end) as [Industry-4]
, min(case when ri.RowNr = 5 then i.name end) as [Industry-5]
from registrants r
join (
select (
select count(*)
from registrants_industries ri3
where ri3.registrant = r2.registrant
and ri3.id <= ri2.id
) as RowNr
, *
from registrants_industries ri2
) ri
on ri.registrant_id = r.id
join industries i
on i.id = ri.industry_id
group by
r.id
, r.first_name
, r.last_name
您要求透视值到各自的列中。这是一个常见的需求,特别是在报告和导出电子表格时。
在SQL中,您需要在查询中声明列,并且在查询准备时,在查询有机会查看数据之前,它们是固定的。您不能让查询根据它找到的数据值动态地自动向其结果集中添加列。
解决方法是为查询结果中包含的每个不同值硬编码表达式:SELECT r.id, r.first_name, r.last_name,
MAX(CASE i.name WHEN 'Painting' THEN i.name END) AS `Painting`,
MAX(CASE i.name WHEN 'Tiling' THEN i.name END) AS `Tiling`,
MAX(CASE i.name WHEN 'General Construction' THEN i.name END) AS `General Construction`,
MAX(CASE i.name WHEN 'Yard Care' THEN i.name END) AS `Yard Care`,
MAX(CASE i.name WHEN 'Roofing' THEN i.name END) AS `Roofing`
FROM registrants r
LEFT OUTER JOIN (
registrants_industries ri
INNER JOIN industries i ON i.id = ri.industry_id
) ON r.id = ri.registrant_id
GROUP BY r.id;
这意味着您需要知道数据中可能存在哪些不同的值,否则您需要在运行上述查询之前发现它:
SELECT DISTINCT name FROM industries;
然后编写应用程序代码,使用该结果生成具有可变列数的SQL查询字符串,每个列表达式对应于不同的行业名称。
另一种方法是不使用SQL进行透视,而是将原始数据获取回应用程序,并为每个用户id获取多行,将结果排序到应用程序数据结构中,直到您拥有一些看起来像您想要的透视数据集的网格视图。
如果您想要一个适合数据的查询并为每个存在的数据值返回一列,那么无论如何您都需要编写应用程序代码。您可以编写代码来预处理数据并生成SQL查询,或者编写代码来在获取数据时对数据进行后处理。