我有 3 个 Mysql 表:
[块值]
- id_block_value
- 文件标识
[元数据]
- id_metadata
- 元数据名称
[元数据值]
- meta_id
- 价值
- blockvalue_id
在这些表中,有对:metadata_name
=value
并且对的列表放在块中 ( id_block_value
)
(A)如果我想要高度 = 1080:
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "height" and value = "1080");
+---------+
| file_id |
+---------+
| 21 |
| 22 |
(...)
| 6962 |
(...)
| 8146 |
| 8147 |
+---------+
794 rows in set (0.06 sec)
(B)如果我想要文件扩展名 = mpeg:
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "file extension" and value = "mpeg");
+---------+
| file_id |
+---------+
| 6889 |
| 6898 |
| 6962 |
+---------+
3 rows in set (0.06 sec)
但是,如果我想:
- 甲和乙
- 甲或乙
- A而不是B
然后,我不知道什么是最好的。
对于A or B
,我尝试A union B
了似乎可以解决问题的方法。
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "height" and value = "1080")
UNION
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "file extension" and value = "mpeg");
+---------+
| file_id |
+---------+
| 21 |
| 22 |
| 34 |
(...)
| 6889 |
| 6898 |
+---------+
796 rows in set (0.13 sec)
对于A and B
,由于Mysql中没有intersect
,我试过了A and file_id in(B)
,但是看看perfs(> 4mn)......
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "height" and value = "1080")
and file_id in(
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "file extension" and value = "mpeg"));
+---------+
| file_id |
+---------+
| 6962 |
+---------+
1 row in set (4 min 36.22 sec)
我也试过B and file_id in(A)
了,好多了,但我永远不知道先放哪个。
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "file extension" and value = "mpeg")
and file_id in(
SELECT DISTINCT file_id
FROM metadata_value MV
INNER JOIN metadata M ON MV.meta_id = M.id_metadata
INNER JOIN block_value BV ON MV.blockvalue_id = BV.id_block_value
WHERE (metadata_name = "height" and value = "1080"));
+---------+
| file_id |
+---------+
| 6962 |
+---------+
1 row in set (0.75 sec)
那么……我现在该怎么办?布尔运算有更好的方法吗?任何提示?我错过了什么?
编辑:什么数据看起来像:
该数据库在FILE
表中包含插入的每个音频/视频文件的一行:
- 10、/path/to/file.ts
- 11、/path/to/file2.mpeg
METADATA
每个潜在信息在表中都有一行:
- 301,身高
- 302,文件扩展名
然后,BLOCK
表中的一行定义了一个容器:
- 101、视频
- 102、音频
- 104、一般
一个文件可以有多个元数据块,一个BLOCK_VALUE
表包含 BLOCKS 的实例:
- 402, 101, 10 // 视频 1
- 403, 101, 10 // 视频 2
- 404, 101, 10 // 视频 3
- 405, 102, 10 // 音频
- 406, 104, 10 // 一般
在本例中,文件 10 有 5 个块:3 个视频 (101) + 1 个音频 (102) + 1 个常规 (104)
值存储在METADATA_VALUE
- 302, 406, "ts" // 文件扩展名,通用
- 301, 402, "1080" // 高度,视频 1
- 301, 403, "720" // 高度,视频 2
- 301, 404, "352" // 高度,视频 3