MySQL - Найти первое совпадение или подстановочный знак - PullRequest
0 голосов
/ 29 января 2019

У меня есть таблица с сопоставленными переменными / столбцами, например:

+------+------+------+------+
| 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`)
);

Я хочу найти первое совпадение с любым столбцом, который вместо этого может вернуть требуемое совпадение из столбца или подстановочного знака.

SELECT * 
FROM test 
WHERE ele = '123' (dim1 = 'DM1' OR dim1 = '*') 
  AND (dim2 = 'DM2' OR dim2 = '*') 
  AND (dim3 = 'DM3' OR dim3 = '*');

Бывает, что при этом возвращаются оба столбца (найдены один и соответствующий шаблон, конечно).

Есть ли какой-нибудь способ найти соответствующий или групповой символ при сбое?

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Не ответ;слишком долго для комментария ...

Нормализованная среда может выглядеть примерно так:

entity dim val
     1   1   *
     1   2   *
     1   3   *
     2   1   DM1
     2   2   *
     2   3   *
0 голосов
/ 30 января 2019

Один из способов сделать это - подсчитать количество совпадений с подстановочными знаками для каждой строки (используя тот факт, что в числовом контексте MySQL рассматривает логическое значение как 1 или 0), а затем упорядочить по этому числу по возрастанию, сLIMIT 1 для возврата только строки с наименьшим количеством подстановочных знаков, например

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

Демонстрация на dbfiddle

0 голосов
/ 30 января 2019

Делайте это как два отдельных запроса, которые вы объединяете с 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
...