Mysql - 灵活的,类似 excel 的结构

mkr*_*arz 5 mysql sql excel

我最近继承了一个已经开始的项目,现在我面临一个挑战。其中一项要求是允许用户在应用程序内创建一个“数据库”,该数据库可以具有可变数量的用户定义列(它是一个类似 excel 的结构)。

这是我当前结构的sqlfiddle

这是我用来获取行的查询:

select      `row`, 
            group_concat(dd.value order by field(`col`, 1, 2, 3) asc) as `values`
from        db_record dr,
            db_dictionary dd
where       dr.database_id in (1, 2, 3)
and         dr.database_dictionary_id = dd.id
group by    `row`
order by    group_concat(dd.value order by field(`col`, 1, 2, 3) asc);
Run Code Online (Sandbox Code Playgroud)

通过使用 group_concat() 可以实现按任何列排序的能力。

我正在考虑那个设计,因为我对性能和满足要求有一些疑问:

  • 它必须是可排序的(按任何列),这意味着用户按第 2 列按 asc 排序,并且行排序正确。
  • 它必须是可搜索/可过滤的。用户可以按任何列中的值进行过滤,并且只应返回包含搜索短语的行。

我认为第一个要求是由我在上面粘贴的查询处理的。第二个 - 我也尝试使用 LIKE 向查询添加 HAVING 子句,但它比较了整个 GROUP_CONCAT() 结果。

有人可以建议,当前的数据库结构是否适合此目的并帮助我满足后一个要求?或者也许有更好的方法来解决这个问题?

最后一个问题,是否可以在一个查询中为每一列返回值?在 DB 中,记录如下所示:

-------------------------------------------
| database_id | dictionary_id | row | col |
-------------------------------------------
| 1           | 1             | 1   | 1   |
-------------------------------------------
| 2           | 2             | 1   | 2   |
-------------------------------------------
| 3           | 3             | 1   | 3   |
-------------------------------------------
Run Code Online (Sandbox Code Playgroud)

我想得到一个按行分组的查询结果,类似于:(第 1 列 .. 3 值是 dictionary_id 值)

----------------------------------------
| row | column 1 | column 2 | column 3 | 
----------------------------------------
| 1   | 1        | 2        | 3        |
----------------------------------------
Run Code Online (Sandbox Code Playgroud)

这在mysql中可以实现吗?或者唯一的解决方案是使用 GROUP_CONCAT() 然后我可以使用 php 拆分成列?

我需要一个灵活而高效的结构,我希望有人能就此提出建议,我非常感谢任何帮助或建议。

mkr*_*arz 1

经过一番思考,我想我可能有一个解决方案,但我不确定这是否是最好的解决方案。在应用程序中运行查询之前,我已经知道虚拟“数据库”有多少列,并且因为我知道需要搜索哪一列(本例中的第 3 列),所以我可以构建如下查询:

select      `row`,
            group_concat(if(field(`column`, 1), dd.value, null)) as column1,
            group_concat(if(field(`column`, 2), dd.value, null)) as column2,
            group_concat(if(field(`column`, 3), dd.value, null)) as column3
from        db_record dr
left join   db_dictionary dd on (dr.dictionary_id = dd.id)
where       dr.database_id = 1
group by    `row`
having      column3 like '%biu%'
order by    `columns` asc;
Run Code Online (Sandbox Code Playgroud)

因此,在 PHP 中,我可以为每一列添加group_concat(if(...))并添加HAVING子句进行搜索。

但如果可能的话,我想获得有关该解决方案的一些反馈。