bounty还有16小时到期。此问题的答案有资格获得+50声望奖励。Dan正在寻找此问题的最新答案。
我正在为客户网站使用Cubecart,他们使用逗号分隔值将某些选项ID与产品相关联。我需要创建一个自定义表,它可以将所有这些信息转换为一种格式,以便我可以为不同的产品选项组合分配不同的产品代码。
产品列表
| 产品编号|产品型号|指定密钥|
| - -----|- -----|- -----|
| 1| ABC| 23,45|
| 1| HIJ|二十三|
| 1|荷航|四十五|
| 2| DEF| 10,28|
| 2| GHI|十个|
| 2| NOP|二十八|
分配表
| 产品编号|分配ID|值ID|
| - -----|- -----|- -----|
| 1|二十三|1|
| 1|四十五|2|
| 2|十个|3|
| 2|二十八|4|
数值表
| 值ID|价值|
| - -----|- -----|
| 1|红色|
| 2|大|
| 3|蓝色|
| 4|小型|
如果赋值键实际上是值ID,我可以计算出如何将products表直接连接到values表,但我无法计算出如何将assign表连接到中间。我需要连接要分配的产品并分配给值。
SELECT
t1.product_code,
t1.product_id,
t1.assign_key,
GROUP_CONCAT(t2.value_name)
FROM products t1
LEFT JOIN values t2 ON FIND_IN_SET(t2.value_id, t1.assign_key)
GROUP BY t1.assign_key
预期输出:
| 产品编号|产品型号|分配ID|值ID|价值观|
| - -----|- -----|- -----|- -----|- -----|
| 1| ABC| 23,45|一二|红色,大号|
| 1| HIJ|二十三|1|红色|
| 1|荷航|四十五|2|大|
| 2| DEF| 10,28|三四|蓝色,小号|
| 2| GHI|十个|3|蓝色|
| 2| NOP|二十八|4|小型|
我尝试在中间添加另一个连接,但无法解决如何将concat分组两次。
我不能只分离赋值键,这样每行只有一个值,因为关键是产品代码只与两个赋值键的组合相关。
3条答案
按热度按时间pprl5pva1#
此查询产生了所需的结果:
输出:
| 产品ID|乘积码|分配ID| ValueID|价值观|
| - -----|- -----|- -----|- -----|- -----|
| 1| ABC| 23,45|一二|红色,大号|
| 1| HIJ|二十三|1|红色|
| 1|荷航|四十五|2|大|
| 2| DEF| 10,28|三四|蓝色,小号|
| 2| GHI|十个|3|蓝色|
| 2| NOP|二十八|4|小型|
在DBFIDDLE中完成了一个(简短的)分步计划,但它基本上是“不断向这个查询添加内容,直到我们获得所有需要的值”,然后应用
GROUP_CONCAT
,以及一个适当的GROUP BY
。(An关于错误“ONLY_FULL_GROUP_BY”的解释,以及如何在查询中解决它,也在DBFIDLE中。)
一些注意事项:
SUBSTRING_INDEX(SUBSTRING_INDEX(assign_key,',',FIND_IN_SET(a.assign_id,p.assign_key)),',',-1)
的目的是在逗号分隔的字符串中查找第n个元素。一个简短的例子:这将返回
d
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('a,b,c,d,e',',',4),',',-1)
6ss1mwsb2#
作为
find_in_set
的替代方案,我们可以使用JSON。一个逗号分隔的整数列表可以很容易地转换成一个JSON数组,方法是用方括号将其括起来;然后,我们可以使用handy JSON functionjson_table
将数组解嵌套到行,同时使用选项with ordinality
跟踪每个元素的原始位置。有了非嵌套的键列表,现在很容易将表
assign
和value
与join
s合并;由于我们有原始索引可用,因此生成CSV值列表是安全和简单的。我们可以用一个横向连接来表示:
或者我们可以直接在外部查询中进行解嵌套和聚合:
这种方法的一个结果是,它将正确处理CSV列表中的重复项(如果有)(而基于
find_in_set
的解决方案通常会删除其中一个重复项)-我将这种情况添加到示例数据中的产品1
中。此外,它避免了对
find_in_set
的重复调用-但当然json_table
也有代价,因此这是否会提高性能在很大程度上取决于您的数据和设置。Demo on DBFiddle
| 产品编号|产品编号|分配密钥(_K)|值ID|值名称|
| - -----|- -----|- -----|- -----|- -----|
| 1| ABC|二十三,四十五,二十三|一,二,一|红色,大号,红色|
| 1| HIJ|二十三|1|红色|
| 1|荷航|四十五|2|大|
| 2| DEF| 10,28|三四|蓝色,小号|
| 2| GHI|十个|3|蓝色|
| 2| NOP|二十八|4|小型|
ie3xauqp3#
你可以使用
find_in_set
...23
和45
将分别在位置1和2的23,45
中找到。这将是join和order by的基础。SQLFiddle