使用MySQL管理型数据库实现不定列数据存储
版权归原作者所有。 本文最后更新于:2023年9月27日 晚上
使用MySQL管理型数据库实现不定列数据存储
有一需求是需要上传一个excel之后进行查看,但是Excel的列是不固定的,还可以进行反复上传,
但是Excel中有一列是必须要有的那就是ID列,这个列可以用来判断第二次上传是更新还是有新加入的数据
就对于这个需求呢,我在MySQL中设计了三张表, 表中重点字段为:
只列举重要字段
第一张表sample字段为:
sample_number(样本编号 - 生成策略当前上传的日期然后另外加入4位数的自增从0001开始例如第一个202012090001)、sample_name(上传excel的名字)、excel_url(上传excel存储在服务器的地址)
第二张表sample_field字段 (存储列名)
sample_number(样本编号)、field_name(字段名称)、field_type(STRING、INT、DATE)(字段类型)、is_primary(是否为主键)、field_index(字段排列顺序)
第三张表sample_data 字段(存储数据):
sample_number(样本编号)、field_name(字段名称)、row_id(行id,用来区分哪些数据是属于同一行)、field_value(具体的列的值,因为字段已经表示了类型,
所以存储的时候直接都存储字符串,根据需要的时候在去做转换)
错误起源
所以,有了上面三张表之后,那就需要查询数据了,在查询数据的过程中呢,因为需要分页和条件筛选,按照逻辑进行组织了SQL,出错了
错误提示
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
在官网中找到了这个限制和解决方式
https://dev.mysql.com/doc/mysql-reslimits-excerpt/8.0/en/subquery-restrictions.html
解决方案:在子查询里面在加入一个孙子查询,把LIMIT进行实现了,就可以规避这个问题
MySQL permits a subquery to refer to a stored function that has data-modifying side effects such as inserting rows into a table. For example, if f() inserts rows, the following query can modify data:
SELECT ... WHERE x IN (SELECT f() ...);
This behavior is an extension to the SQL standard. In MySQL, it can produce nondeterministic results because f() might be executed a different number of times for different executions of a given query depending on how the optimizer chooses to handle it.
For statement-based or mixed-format replication, one implication of this indeterminism is that such a query can produce different results on the source and its slaves.
最终实现SQL
SELECT
hsd.row_id,
hsd.sample_number,
hsd.field_name,
hsd.field_value
FROM
hwcss_sample_data AS hsd
WHERE
EXISTS (
SELECT
row_id
FROM
( SELECT row_id FROM hwcss_sample_data phsd WHERE del_flag = 0
AND EXISTS (SELECT row_id FROM hwcss_sample_data WHERE field_name = 'S_Serial' AND field_value = '1001' AND phsd.row_id = row_id )
AND EXISTS (SELECT row_id FROM hwcss_sample_data WHERE field_name = 'ID' AND field_value = 'B112527' AND phsd.row_id = row_id )
# TODO 可以再加入筛选条件
GROUP BY row_id LIMIT 10 OFFSET 1 ) AS ihsd
WHERE
hsd.row_id = ihsd.row_id
)
ORDER BY
hsd.row_id
索引优化
在 row_id 和 field_name 上面做了索引优化,使用B+TREE索引,索引类型为 NORMAL
附录:
MySQL单表数据限制:https://dev.mysql.com/doc/refman/8.0/en/table-size-limit.html
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明蚁点博客出处!