基于 2 个表和一个连接表和行的 MySQL 查询应按顺序包含连接数据的所有实例

发布于 2024-12-23 16:22:22 字数 955 浏览 2 评论 0原文

我需要创建一个包含来自 2 个表的数据的表结果(并查明在 MySQL 的限制内是否可能),但查询本身将基于 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 等中排序。

此查询输出是否可以使用 (My)SQL 进行? 如果可以,您可以对此最好的方法有什么好的建议吗?

我开始编写查询,却发现没有答案可以根据匹配项解决我添加的列。并根据我的需要将所有内容按行组合在一起。

I need to create a table result (and find out if it IS possible within the constraints of MySQL) that will contain data from 2 tables, but the query itself will be based on 3 tables (including a join-table). And joined results should be added to the output results.

Table Structures:

registrants
id, first name, last name, industryID

industries
id, name

registrants_industries (join table)
id, registrant_id, industry_id

So in the final output results table, any registrant could have 0, 1 or many industries, and those industry names should be tacked onto the end of the final results table.

registrants.id, 
registrants.first_name, 
registrants.last_name, 
industry.name-1,      
industry.name-2,  
industry.name-3,  
industry.name-4,  
industry.name-5.

But all columns should align by industry. For example, if there were 5 industries, the output would be like so:

(Industries are in this order:
Painting, Tiling, General Construction, Yard Care, Roofing)

354, Mike, Smith, Painting,’’,’’,Yard Care,’’
599, Joe, Jones, ‘’,’’,’General Construction’,’’,’’

So all industry columns would align and could be sorted in Excel etc.

Is this query output with (My)SQL possible? And if so, an you make any good suggestion on the best approach to this?

I began writing my query only to find no answers that solve my added columns based on matches. And getting it all together by row as I need.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

So要识趣 2024-12-30 16:22:22

您可以使用 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’"

You could use group_concat and get all the industries in a single column. I'm aware that is not an exact answer to your questions, but it comes close and I don't believe what you ask is possible with only 3 joins.

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

This will produce

354, Mike, Smith, "Painting,Yard Care"
599, Joe, Jones, "’General Construction’"
漫漫岁月 2024-12-30 16:22:22

您可以使用子查询为每个 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

You can assign a number to each registrants_industries entry using a subquery:

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
优雅的叶子 2024-12-30 16:22:22

您要求将值透视到相应的列中。这是一个常见的要求,特别是对于报告和导出到电子表格而言。

在 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 查询,或者编写代码来在获取数据时对数据进行后处理。

You're asking to pivot values into respective columns. This is a common requirement especially for reporting and exporting to spreadsheets.

In SQL, you need to declare the columns in the query, and they are fixed at query prepare time, before your query gets a chance to look at the data. You can't have a query automatically add columns to its result set dynamically, based on the data values it finds.

The workaround is to hard-code expressions for each distinct value you will include in the query result:

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;

This means you either need to know what distinct values possibly exist among your data, or else you need to discover it before you run the above query:

SELECT DISTINCT name FROM industries;

Then write application code to use that result to generate an SQL query string with a variable number of columns, one column expression corresponding to each distinct industry name.

The alternative is to not pivot using SQL, but instead fetch the raw data back to your application, and fetch multiple rows per user id, sorting results into an application data structure until you have some grid view that looks like the pivoted data set you want.

One way or the other you need to write application code, if you want a query that adapts to the data and returns a column for each data value that exists. You either write code to pre-process data and generate an SQL query, or else you write code to post-process the data as you fetch it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文