我需要从MySQL数据库中导出一个列,该列只显示每个条目一次。所以在下表中:
id author(s) content
________________________________________
1 Bill, Sara, Mike foo1
1 Sara foo2
2 Bill, Sara, Mike foo3
2 Sara foo4
3 David foo5
3 Mike foo5
我需要将作者列表导出为“Bill,Sara,Mike,Susan”,以便每个名称只显示一次。
谢谢!
UPDATE:我意识到这可能是不可能的,所以我将不得不接受一个导出的列表,它只是消除了列中的任何精确重复,因此输出将是这样的: strong> Bill,Sara,Mike,Sara,David,Mike 任何形成此查询的帮助都将不胜感激。
再次感谢!
答案 0 :(得分:1)
可以获得结果集,但我实际上只是将它转换为另一个表,每个作者一行。我不想从应用程序代码中运行这样的查询。
SUBSTRING_INDEX
函数可用于提取第一个,secpond等。列表中的作者,例如
SUBSTRING_INDEX(SUBSTRING_INDEX(authors,',', 1 ),',',-1) AS author1
SUBSTRING_INDEX(SUBSTRING_INDEX(authors,',', 2 ),',',-1) AS author2
SUBSTRING_INDEX(SUBSTRING_INDEX(authors,',', 3 ),',',-1) AS author3
但是这最终会变得混乱,因为当你检索超出列表的长度时,你会得到最后一位作者。
所以,你可以用一个相当丑陋的表达来计算逗号的数量:
LENGTH(authors)-LENGTH(REPLACE(authors,',','')) AS count_commas
但是附加一个尾随的逗号同样容易,然后将空字符串转换为NULL 所以,用以下内容替换作者:
CONCAT(authors,',')
然后将其包装在TRIM和NULLIF函数中。
NULLIF(TRIM( foo ),'')
然后,您可以编写一个查询从每一行获取第一个作者,另一个查询从每一行获取第二个作者(与第一个查询相同,只需将'1'更改为'2',第三个作者等,最多可达列值中的最大作者数。将所有这些查询与UNION操作结合在一起(这将消除重复项。)
所以,这个查询:
SELECT NULLIF(TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(a.authors,','),',',1),',',-1)),'') AS author
FROM unfortunately_designed_table a
UNION
SELECT NULLIF(TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(a.authors,','),',',2),',',-1)),'')
FROM unfortunately_designed_table a
UNION
SELECT NULLIF(TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(a.authors,','),',',3),',',-1)),'')
FROM unfortunately_designed_table a
UNION
SELECT NULLIF(TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(a.authors,','),',',4),',',-1)),'')
FROM unfortunately_designed_table a
这将返回唯一作者姓名的结果集(并且无疑是NULL)。这只是列表中的前四位作者,你需要扩展它以获得第五,第六等等。
您可以通过查找逗号的最大数量并添加1
来获取该列中条目的最大数量SELECT MAX(LENGTH(a.authors)-LENGTH(REPLACE(a.authors,',','')))+1 AS max_count
FROM unfortunately_designed_table a
这可以让你知道你需要在多长时间内扩展上面的查询以获取所有作者值(在特定时间点运行查询...没有任何东西阻止某人将另一位作者添加到列中的列表中在以后的时间。
完成所有工作以在不同的行上获取不同的作者值之后,您可能希望将它们保留在这样的列表中。它更容易使用。
但是,当然,也可以将结果集转换回逗号分隔列表,但返回的字符串大小受max_allowed_packet
会话变量(iirc)的限制。
要将其作为单行返回,使用逗号分隔的列表,从上面获取整个查询的混乱,并将其作为线视图包装在parens中,给它一个别名,并使用{{1}功能。
GROUP_CONCAT
如果你认为所有这些表达都是丑陋的,并且应该有一种更简单的方法来做到这一点,不幸的是(除了编写程序代码),实际上并非如此。关系数据库旨在处理元组(行)中的信息,每行代表一个实体。将多个实体或值填充到单个列中违背了关系设计。因此,SQL没有提供一种简单的方法来将字符串中的值提取到单独的元组中,这就是为什么执行此操作的代码非常混乱的原因。