MySQL - 查找第一个匹配项或通配符
MySQL - Find first match or wildcard
我有一个 table 映射 variables/columns,例如:
+------+------+------+------+
| ele | dim1 | dim2 | dim3 |
+------+------+------+------+
| 123 | * | * | * |
| 123 | DM1 | * | * |
| abc | * | DM2 | * |
+------+------+------+------+
CREATE TABLE `test`
(
`ele` varchar(36) NOT NULL,
`dim1` varchar(36) NOT NULL,
`dim2` varchar(36) NOT NULL,
`dim3` varchar(36) NOT NULL,
UNIQUE KEY `test_dim1_dim2_dim3_uindex` (`ele`, `dim1`,`dim2`,`dim3`)
);
我想找到第一个与可能 return 需要来自列或通配符的匹配项的列的匹配项。
SELECT *
FROM test
WHERE ele = '123' (dim1 = 'DM1' OR dim1 = '*')
AND (dim2 = 'DM2' OR dim2 = '*')
AND (dim3 = 'DM3' OR dim3 = '*');
碰巧这 return 两列(当然找到一个和通配符匹配)。
有什么方法可以在失败时找到匹配项或通配符吗?
将其作为两个单独的查询执行,然后与 UNION
结合使用。给他们每个人一个排序列,并使用它来更喜欢真正的匹配而不是通配符。
SELECT *
FROM (
SELECT 1 AS o, test.*
FROM test
WHERE dim1 = 'DM1' OR dim2 = 'DM2' OR dim3 = 'DM3'
LIMIT 1
UNION
SELECT 2 AS o, test.*
FROM test
WHERE dim1 = '*' AND dim2 = '*' AND dim3 = '*'
LIMIT 1
) AS x
ORDER BY o
LIMIT 1
不是答案;评论太长了...
规范化的环境可能看起来更像这样:
entity dim val
1 1 *
1 2 *
1 3 *
2 1 DM1
2 2 *
2 3 *
这样做的一种方法是计算每一行的通配符匹配项的数量(利用在数字上下文中 MySQL 将布尔值视为 1 或 0 的事实)然后排序按该数字升序,从 LIMIT 1
到 return 只有通配符匹配次数最少的行,例如
SELECT *
FROM test
WHERE ele = 123 AND
(dim1 = 'DM1' OR dim1 = '*') AND
(dim2 = 'DM2' OR dim2 = '*') AND
(dim3 = 'DM3' OR dim3 = '*')
ORDER BY (dim1 = '*') + (dim2 = '*') + (dim3 = '*') ASC
LIMIT 1
输出:
ele dim1 dim2 dim3
123 DM1 * *
我有一个 table 映射 variables/columns,例如:
+------+------+------+------+
| ele | dim1 | dim2 | dim3 |
+------+------+------+------+
| 123 | * | * | * |
| 123 | DM1 | * | * |
| abc | * | DM2 | * |
+------+------+------+------+
CREATE TABLE `test`
(
`ele` varchar(36) NOT NULL,
`dim1` varchar(36) NOT NULL,
`dim2` varchar(36) NOT NULL,
`dim3` varchar(36) NOT NULL,
UNIQUE KEY `test_dim1_dim2_dim3_uindex` (`ele`, `dim1`,`dim2`,`dim3`)
);
我想找到第一个与可能 return 需要来自列或通配符的匹配项的列的匹配项。
SELECT *
FROM test
WHERE ele = '123' (dim1 = 'DM1' OR dim1 = '*')
AND (dim2 = 'DM2' OR dim2 = '*')
AND (dim3 = 'DM3' OR dim3 = '*');
碰巧这 return 两列(当然找到一个和通配符匹配)。
有什么方法可以在失败时找到匹配项或通配符吗?
将其作为两个单独的查询执行,然后与 UNION
结合使用。给他们每个人一个排序列,并使用它来更喜欢真正的匹配而不是通配符。
SELECT *
FROM (
SELECT 1 AS o, test.*
FROM test
WHERE dim1 = 'DM1' OR dim2 = 'DM2' OR dim3 = 'DM3'
LIMIT 1
UNION
SELECT 2 AS o, test.*
FROM test
WHERE dim1 = '*' AND dim2 = '*' AND dim3 = '*'
LIMIT 1
) AS x
ORDER BY o
LIMIT 1
不是答案;评论太长了...
规范化的环境可能看起来更像这样:
entity dim val
1 1 *
1 2 *
1 3 *
2 1 DM1
2 2 *
2 3 *
这样做的一种方法是计算每一行的通配符匹配项的数量(利用在数字上下文中 MySQL 将布尔值视为 1 或 0 的事实)然后排序按该数字升序,从 LIMIT 1
到 return 只有通配符匹配次数最少的行,例如
SELECT *
FROM test
WHERE ele = 123 AND
(dim1 = 'DM1' OR dim1 = '*') AND
(dim2 = 'DM2' OR dim2 = '*') AND
(dim3 = 'DM3' OR dim3 = '*')
ORDER BY (dim1 = '*') + (dim2 = '*') + (dim3 = '*') ASC
LIMIT 1
输出:
ele dim1 dim2 dim3
123 DM1 * *