我的问题我有一个表apidata
,它为每个域保存多行数据。因此,当我查询apidata
时,我自然会得到多行。有没有办法将这些行转换为列?我问,因为我已经使用查询来提取域数据(页面标题,URL,顶级域名,IP地址等),我需要添加api数据。我相信我必须在两个查询中执行此操作,但我希望每个域至少有一行来进行查询并尽可能快地循环。
所以问题是,我可以动态创建行吗?
下一个SQL小提琴=> http://sqlfiddle.com/#!2/8e408/4
(注意,我并没有将整个数据库放在影响查询的表格中。如果你认为缺少了你需要的东西,请告诉我。)
Tool_Runs (id_sha是工具运行的主要查找值)
| ID | ID_SHA |
+----+------------------------------------------+
| 1 | 68300DF58B2A8A6E098CB0B3D1A9AE80BBE5897A |
域(Run_id是FK到tool_runs.id)
| ID | RUN_ID |
+----+--------+
| 1 | 1 |
API数据
| ID | DOMAIN_ID | EXPORT_COLUMN | COLUMN_TITLE | VALUE |
+----+-----------+------------------+-------------------+-------+
| 1 | 1 | referringDomains | Referring Domains | 10 |
+----+-----------+------------------+-------------------+-------+
| 2 | 1 | linkCount | Backlink Count | 55 |
现在是我的查询:
SELECT a.domain_id, a.export_column, a.column_title, a.value
FROM apidata AS a WHERE domain_id IN
(
SELECT d.id FROM tool_runs AS t
JOIN domains AS d ON d.run_id = t.id
WHERE id_sha = '68300DF58B2A8A6E098CB0B3D1A9AE80BBE5897A'
)
ORDER BY a.domain_id
我得到的是:
| DOMAIN_ID | EXPORT_COLUMN | COLUMN_TITLE | VALUE |
+-----------+------------------+-------------------+----------+
| 1 | referringDomains | Referring Domains | 10 |
+-----------+------------------+-------------------+----------+
| 1 | linkCount | Backlink Count | 55 |
但我想要的是
| DOMAIN_ID | referringDomains | referringDomains_TITLE | linkCount | linkCount_TITLE |
+-----------+------------------+------------------------+-----------+-----------------+
| 1 | 10 | Referring Domains | 55 | Backlink Count |
答案 0 :(得分:1)
您尝试将数据表行转换为列。不幸的是,MySQL没有本地数据透视表操作符,但您可以使用CASE
表达式来执行此操作:
SELECT
a.Domain_id,
MAX(CASE WHEN a.export_column = 'referringDomains' THEN a.value END) AS referringDomains,
MAX(CASE WHEN a.export_column = 'referringDomains' THEN a.column_title END) AS referringDomains_TITLE,
MAX(CASE WHEN a.export_column = 'linkCount' THEN a.value END) AS linkCount,
MAX(CASE WHEN a.export_column = 'linkCount' THEN a.column_title END) AS linkCount_TITLE
FROM apidata AS a
WHERE domain_id IN
(
SELECT d.id FROM tool_runs AS t
JOIN domains AS d ON d.run_id = t.id
WHERE id_sha = '68300DF58B2A8A6E098CB0B3D1A9AE80BBE5897A'
)
GROUP BY a.domain_id;
请注意:如果要对export_column
中的所有值执行此操作,则必须为每个值编写CASE
表达式。但你可以使用动态sql这样做:
SET @ecvalues = NULL;
SET @ectitles = NULL;
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(a.export_column = ''',
a.export_column, ''', a.value , NULL)) AS ', '''', a.export_column , '''')
) INTO @ecvalues
FROM apidata a;
SELECT
GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(a.export_column = ''',
a.export_column, ''', column_title , NULL)) AS ', '''', CONCAT(a.export_column , '_Titles'), '''')
) INTO @ectitles
FROM apidata a;
SET @sql = CONCAT('SELECT
a.Domain_id, ', @ectitles , ',', @ecvalues, '
FROM apidata AS a
WHERE domain_id IN
(
SELECT d.id FROM tool_runs AS t
JOIN domains AS d ON d.run_id = t.id
WHERE id_sha = ''68300DF58B2A8A6E098CB0B3D1A9AE80BBE5897A''
)
GROUP BY a.domain_id;');
prepare stmt
FROM @sql;
execute stmt;
您可以将该查询放在存储过程中。
答案 1 :(得分:0)
作为@MahmoudGamal答案的补充,您应该知道,对于任何新的注册表(EXPORT_COLUMN
),您都必须添加新的case
语句。
因此,为了实现动态,您可以在dba.stackexchange上创建一个过程,如本文所述。
How to transpose/convert rows as columns in mysql
它显示了如何动态地完成它。
答案 2 :(得分:0)
如果您想要列,请按照上面的示例继续进行转动。如果您只想要一个字符串,出于某些报告原因,请继续:
SELECT group_concat(CONCAT_WS(' ',a.domain_id, a.value, a.column_title, a.export_column, 'next row string separator'))
FROM apidata AS a WHERE domain_id IN
(
SELECT d.id FROM tool_runs AS t
JOIN domains AS d ON d.run_id = t.id
WHERE id_sha = '68300DF58B2A8A6E098CB0B3D1A9AE80BBE5897A'
)
ORDER BY a.domain_id