从MySQL中的行动态创建列
我有以下表格:从MySQL中的行动态创建列,mysql,sql,pivot,crosstab,Mysql,Sql,Pivot,Crosstab,我有以下表格: "crawlresults" id | url | fk_crawljobs_id --------------------------------------------- 1 | shop*com/notebooks | 1 2 | shop*com/fridges | 1 3 | website*com/lists | 2 "extractions" id | fk_extracto
"crawlresults"
id | url | fk_crawljobs_id
---------------------------------------------
1 | shop*com/notebooks | 1
2 | shop*com/fridges | 1
3 | website*com/lists | 2
"extractions"
id | fk_extractors_id | data | fk_crawlresults_id
---------------------------------------------------------------
1 | 1 | 123.45 | 1
2 | 2 | notebook | 1
3 | 3 | ibm.jpg | 1
4 | 1 | 44.5 | 2
5 | 2 | fridge | 2
6 | 3 | picture.jpg | 3
7 | 4 | hello | 3
8 | 4 | world | 3
9 | 5 | hi | 3
10 | 5 | my | 3
11 | 5 | friend | 3
"extractors"
id | extractorname
----------------------
1 | price
2 | article
3 | imageurl
4 | list_1
5 | list_2
我需要构造一个select语句来获取提取器表中每个提取器的列,提取器表在提取器表中使用
例如:
url | price | article | imageurl
--------------------------------------------------------
shop*com/notebooks | 123.45 | notebook | ibm.jpg
shop*com/fridges | 44.5 | fridge | NULL
我不知道在执行select语句时存在多少extractornames,因此必须动态构建它
编辑:
我忘了提到在我的摘录中可能有多个“列表”。在这种情况下,我需要一个结果集
例2:
url | list_1 | imageurl | list_2
--------------------------------------------------------
website*com/lists | hello | picture.jpg | NULL
website*com/lists | world | picture.jpg | NULL
website*com/lists | NULL | picture.jpg | hello
website*com/lists | NULL | picture.jpg | my
website*com/lists | NULL | picture.jpg | friend
谢谢大家! 您正在寻找的
代码:
基本上,您最初的查询生成了一个虚假的
@sql
变量,它并没有真正为每个提取名称提取数据。创建@sql
也不需要所有这些连接。您只需要每个属性名(来自提取器
表)和对包含期望值的列的引用(数据
)
当对结构有疑问时,为一组固定的属性编写一个简单的pivot查询。这样就很容易识别用于编写动态查询的模式
SELECT c.url,
MAX(IF(pa.extractorname = 'price', p.data, NULL)) AS price,
MAX(IF(pa.extractorname = 'article', p.data, NULL)) AS article,
MAX(IF(pa.extractorname = 'imageurl', p.data, NULL)) AS imageurl
FROM crawlresults c
LEFT JOIN extractions p on (c.id = p.fk_crawlresults_id)
LEFT JOIN extractors pa on (p.fk_extractors_id = pa.id)
WHERE c.fk_crawljobs_id = 1
GROUP BY c.id
至于查询的其余部分,这没关系,请记住,如果对某些爬网结果没有提取,则左连接可能很有用。另外,如果表中每个url
/fk\u crawljobs\u id
可以包含多个crawlresult
,那么按url
分组是个坏主意(MAX
可能会混合多个提取的结果)。另一个类似的问题MySQL中没有pivot查询。事实上,这些类型的查询不属于数据库,因为它们的结果本身不是表;pivot转换属于数据库顶部的应用程序层。@Tomas,检查我的答案,你所需要的只是一个准备好的语句和一些爱。不需要将应用程序层放在下面:)。@AnthonyAccioly看起来不像执行pivot查询的好方法。我认为更可行的方法是在Java/PHP/ASP/C#/which中找到一些pivot转换库(类似于R中的cast
函数-非常简单的用法)而不是一次又一次地调试一些复杂的SQL:-)@AnthonyAccioly我认为应用层正是它所属的地方。当我在提取器表中有一个额外的提取器名称,而该名称没有链接到提取器表中时,它仍然会成为结果集中的一列。另一个问题是当我有一个或多个提取列表时。我已经相应地编辑了我的问题。Jimbo,关于链接很简单,只需过滤与该查询()相关的extractorname
,只需相应地更新创建@sql
的子句即可。现在在多值行上重复单值结果。最后一把小提琴正是我所需要的。非常感谢!:-)
SELECT c.url,
MAX(IF(pa.extractorname = 'price', p.data, NULL)) AS price,
MAX(IF(pa.extractorname = 'article', p.data, NULL)) AS article,
MAX(IF(pa.extractorname = 'imageurl', p.data, NULL)) AS imageurl
FROM crawlresults c
LEFT JOIN extractions p on (c.id = p.fk_crawlresults_id)
LEFT JOIN extractors pa on (p.fk_extractors_id = pa.id)
WHERE c.fk_crawljobs_id = 1
GROUP BY c.id