SQL (lite) Отображение значений - PullRequest
1 голос
/ 29 января 2020

У меня есть простая таблица SQL, отображающая Имя (текст) и Значение (текст). Значение может быть int, float и string. И на мой вопрос, в некоторых случаях значение может иметь отображение, в то время как во всех других случаях значение должно отображаться как есть. Как правильно SQL способ сделать это, учитывая, что БД будет содержать несколько таблиц сопоставления.

возьмем следующий пример:

Запрос необработанный:

temp1 , 3.2       (As is)
temp2 , 20.0      (As is)
Valve , 0         (map 0 / 1 to close / open)
Engin3, 1         (map 0,1,2,3 -> running, idle, stopped, off)
Sysflag, A        (As is)

query w Mapping:

temp1, 3.2
temp2, 20.0
Valve, Closed
Engin1, Idle
SysFlag, A

Спасибо

Продолжить ...

GMB, спасибо за ваш отзыв. Я вижу, как обработка сопоставления с помощью case case имеет смысл в ограниченном примере, который я привел. Для моей базы данных IRL я думаю, что создание таблицы сопоставления является более подходящим. Мне также нравится идея маленького запроса, но скорость равна prio 1 (работает на встроенном устройстве). Мой уровень SQL knowlage ниже уровня определения чистых sql табличных отношений и правил, кроме случаев, когда тип определен в таблице сопоставления, а значение не определено, текст значения должен отображать «error (value)» ".

Итак, для моего простого примера БД, пожалуйста, помогите понять ваше последнее предложение с таблицей сопоставления и что я делаю неправильно:

CREATE TABLE IF NOT EXISTS devtbl(Name TEXT, Value TEXT);
INSERT INTO devtbl VALUES('temp1'   , '3.2' );
INSERT INTO devtbl VALUES('temp2'   , '20.0');
INSERT INTO devtbl VALUES('Valve1'   , '0'   );
INSERT INTO devtbl VALUES('Engin1'  , '1'   );
INSERT INTO devtbl VALUES('System'  , 'A'   );

CREATE TABLE IF NOT EXISTS mappingtbl(Name TEXT, Value TEXT, Mapped_Value TEXT);
INSERT INTO mappingtbl VALUES ('Valve1' ,'0','close' );
INSERT INTO mappingtbl VALUES ('Valve1' ,'1','open'  );
INSERT INTO mappingtbl VALUES ('Engin1','0','running');
INSERT INTO mappingtbl VALUES ('Engin1','1','idle'  );
INSERT INTO mappingtbl VALUES ('Engin1','2','stoppe');
INSERT INTO mappingtbl VALUES ('Engin1','3','off'   );

Выполнение запроса приводит к следующему выводу в sqlite3

select devtbl.Name, coalesce(devtbl.Value, mappingtbl.Mapped_Value) 
from devtbl left join mappingtbl 
on mappingtbl.Name = devtbl.Name and mappingtbl.Value = devtbl.Value;

Name        Value
--------------------------
temp1       3.2
temp2       20.0
Valve1      0
Engin1      1
System      A

Что-то не поддерживается в sqlite3, неправильная идея или неправильный запрос?

Требуемый результат:

Name        Value
--------------------------
temp1       3.2
temp2       20.0
Valve1      Close
Engin1      idle
System      A

Я предполагал наличие столбца в devtbl с ссылка на таблицу сопоставления. Если ссылка на таблицу сопоставления существует, используйте mapped_value, иначе выведите значение devtbl.

DevTbl:

Name        Value       MappingRef
-------------------------------------
temp1       3.2
temp2       20.0
Valve1      0       ValveMap
Engin1      1       EnginMap
System      A

ValveMap:

Value       map_value
-------------------------------------
0   close
1   open

EnginMap:

Value       map_value
-------------------------------------
0   running
1   idle
2   stopped
3   off

Кроме того, если значение не существует в таблице сопоставления, отобразится ошибка. Каким будет запрос sq для этого случая? Каков наилучший, правильный, чистый и самый быстрый способ сделать это?

1 Ответ

1 голос
/ 29 января 2020

Вы можете выполнить транскодификацию в двухуровневом выражении case, например:

select
    name,
    case name
        when 'temp1' then value 
        when 'temp2' then value
        when 'Valve'
            then case value
                when '0' then 'close'
                when '1' then 'open'
            end
        when 'Engin1'
            then case value
                when '0' then 'running'
                when '1' then 'idle'
                when '2' then 'stopped'
                when '3' then 'off'
            end
        when 'SysFlag' then value
    end
from mytable

Вы можете слегка сократить выражение case следующим образом:

case 
    when name in ('temp1', 'temp2', 'SysFlag') then value
    when name = 'Valve'
        then case value
            when '0' then 'close'
            when '1' then 'open'
        end
    when name = 'Engin1'
        then case value
            when '0' then 'running'
            when '1' then 'idle'
            when '2' then 'stopped'
            when '3' then 'off'
        end
end

Один из способов действительно упростить этот запрос - создать отдельную таблицу для хранения сопоставления, что-то вроде:

name        value        mapped_value
Valve       0            close
Valve       1            open
Engin1      0            running
Engin1      1            idle
Engin1      2            stopped
Engin1      3            off

Затем вы можете left join таблица сопоставления в вашем запросе:

select t.name, coalesce(m.vaue, t.mapped_value)
from mytable t
left join mapping_table m on m.name = t.name and m.value = t.value
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...