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     *       *

Demo on dbfiddle