满足条件的SQLite查询执行

时间:2019-07-28 03:34:53

标签: sql sqlite case-when

我正在尝试提出一个SQLite查询,该查询将在满足条件时检索查询中两个给定值(A和B)之间的所有行值。

if(给定的值B大于表中B的最大值):     -检索A和B之间的所有值

样品表:库存

Prod_name |    model     | location | 
tesla     |   "5.6.1"    |    CA
toyota    |   "4.7.1"    |     WA
kia       |   "6.8.1"    |     MD
tesla     |   "2.6.2"    |     CA
chev      |   "7.8.4"    |     AZ


Input given : model between ("5.0.0" to "8.2.0")
Output : (telsa,5.6.1,CA),(kia,6.8.1,MD) , (chev,7.8.4,AZ)

Input given : model between ("5.0.0" to "6.9.0")
Output: Query should not run as "7.8.4" > "6.9.0" 
i.e ( the max value in the table is greater than the upper limit of input query. 
Also to note is the model name is TEXT format. I need help to retrieving   

I have tried "CASE" statements of sqlite but was not able to retrieve 
multiple columns in the subquery.  

select
case
when (select 1000000 * replace(model, '.', 'x') +
1000 * replace(substr(model, instr(model, '.') + 1), '.', 'x') +
replace(model, '.', '000') % 1000 as md from inventory ORDER BY md 
DESC LIMIT 1) > (select 1000000 * replace('5.0.0', '.', 'x') +
1000 * replace(substr('5.0.0', instr('5.0.0', '.') + 1), '.', 'x') +
replace('5.0.0', '.', '000') % 1000)
THEN (select model from inventory where 
1000000 * replace(model, '.', 'x') +
1000 * replace(substr(model, instr(model, '.') + 1), '.', 'x') +
replace(model, '.', '000') % 1000 
between 
1000000 * replace('5.0.0' '.', 'x') +
1000 * replace(substr(''5.0.0'', instr('5.0.0', '.') + 1), '.', 
'x') +
replace('5.0.0', '.', '000') % 1000
and
1000000 * replace('8.5.0', '.', 'x') +
1000 * replace(substr('8.5.0', instr('8.5.0', '.') + 1), '.', 'x') +
replace('8.5.0', '.', '000') % 1000 )
END from inventory

1 个答案:

答案 0 :(得分:1)

我相信以下内容可以满足您的需求:-

/* Query using model in n.n.n format */
SELECT * FROM inventory 
WHERE 
    ((1000000 * substr(model,1,instr(model,'.')-1)) + 
    (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
    replace(model,'.','000') % 1000)
    BETWEEN
        (
            SELECT 1000000  * substr('5.0.0',1,instr('5.0.0','.') -1) 
                + (1000 * replace(substr('5.0.0',instr('5.0.0','.') + 1),'.','x'))
                + replace('5.0.0','.','000') % 1000
        )
        AND
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        )
    /* MAX COndition */
    AND 
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        ) 
            >  
        (
            SELECT MAX(((1000000 * substr(model,1,instr(model,'.')-1)) 
                + (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) 
                + replace(model,'.','000') % 1000)) 
            FROM inventory
        )
ORDER BY 
    (1000000 * substr(model,1,instr(model,'.')-1)) + 
            (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
            replace(model,'.','000') % 1000
;
  

我很好奇如何在当前解决方案中使用它。   或者,如果您有其他方法?

我建议您使用格式为n.n.n的模型来使事情复杂化。

如果要将模型转换为整数值,则可以大大简化问题。

如果您真的想将模型保持为n.n.n,则可以更改表以添加将模型存储为整数的列。例如您可以使用:-

ALTER TABLE inventory ADD COLUMN model_value INTEGER DEFAULT -1;
  • 这将添加列model_value

在ALTER之后可以进行批量UPDATE,然后为现有行设置值,例如:-

UPDATE inventory SET model_value = 
    (1000000 * substr(model,1,instr(model,'.')-1)) + 
    (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
    replace(model,'.','000') % 1000;

要避免需要更改插入内容并预先计算model_value,可以添加AFTER INSERT TRIGGER,例如:-

CREATE TRIGGER IF NOT EXISTS inventory_generate_modelvalue  AFTER INSERT ON inventory
BEGIN
    UPDATE inventory 
        SET model_value = (1000000 * substr(model,1,instr(model,'.')-1)) + 
            (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
            replace(model,'.','000') % 1000
    WHERE model_value < 0 OR model_value IS NULL
        ;
END;
  • 请注意,如果当前使用INSERT时未指定列,则必须对插入进行调整以指定要用于插入的列,或者可以为新列硬编码-1或NULL。

查询将更简单::-

/* Query using model_value) */
SELECT * FROM inventory
WHERE model_value 
    BETWEEN 
        (
            SELECT 1000000  * substr('5.0.0',1,instr('5.0.0','.') -1) 
                + (1000 * replace(substr('5.0.0',instr('5.0.0','.') + 1),'.','x'))
                + replace('5.0.0','.','000') % 1000
        ) 
        AND
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        )
    AND 
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        ) 
            > 
        (SELECT MAX(model_value) FROM inventory)

ORDER BY model_value
;

如果您想将模型值转换为n.n.n格式,则可以基于此使用:-

SELECT prod_name, 
    CAST (model_value / 1000000 AS TEXT)
        ||'.'
        || CAST((model_value % 1000000) / 1000 AS TEXT)
        ||'.'
        ||CAST(model_value % 1000 AS TEXT) 
        AS model, 
    location 
FROM inventory;

当然,如果您的程序中有函数或使用整数而不是n.n.n,那么事情就更简单了。

测试

以下代码用于测试上述内容:-

DROP TABLE IF EXISTS inventory;
DROP TRIGGER IF EXISTS inventory_generate_modelvalue;
CREATE TABLE IF NOT EXISTS inventory (prod_name TEXT ,model TEXT,location TEXT);
INSERT INTO inventory VALUES ('tesla','5.6.1','CA'),('toyota','4.7.1','WA'),('kia','6.8.1','MD'),('tesla','2.6.2','CA'),('chev','7.8.4','AZ') ;

/* Add new column for model as an integer value */
ALTER TABLE inventory ADD COLUMN model_value INTEGER DEFAULT -1;

/* Update existing data for new column */
UPDATE inventory SET model_value = 
    (1000000 * substr(model,1,instr(model,'.')-1)) + 
    (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
    replace(model,'.','000') % 1000;

CREATE TRIGGER IF NOT EXISTS inventory_generate_modelvalue  AFTER INSERT ON inventory
BEGIN
    UPDATE inventory 
        SET model_value = (1000000 * substr(model,1,instr(model,'.')-1)) + 
            (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
            replace(model,'.','000') % 1000
    WHERE model_value < 0 OR model_value IS NULL
        ;
END;

-- INSERT INTO inventory VALUES('my new model','5.0.1','AA',null),('another','0.999.999','ZZ',-1);

SELECT * FROM inventory;

/* Query using model in n.n.n format */
SELECT * FROM inventory 
WHERE 
    ((1000000 * substr(model,1,instr(model,'.')-1)) + 
    (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
    replace(model,'.','000') % 1000)
    BETWEEN
        (
            SELECT 1000000  * substr('5.0.0',1,instr('5.0.0','.') -1) 
                + (1000 * replace(substr('5.0.0',instr('5.0.0','.') + 1),'.','x'))
                + replace('5.0.0','.','000') % 1000
        )
        AND
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        )
    /* MAX COndition */
    AND 
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        ) 
            >  
        (
            SELECT MAX(((1000000 * substr(model,1,instr(model,'.')-1)) 
                + (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) 
                + replace(model,'.','000') % 1000)) 
            FROM inventory
        )
ORDER BY 
    (1000000 * substr(model,1,instr(model,'.')-1)) + 
            (1000 * replace(substr(model,instr(model,'.') + 1),'.','x')) +
            replace(model,'.','000') % 1000
;

/* Query using model_value) */
SELECT * FROM inventory
WHERE model_value 
    BETWEEN 
        (
            SELECT 1000000  * substr('5.0.0',1,instr('5.0.0','.') -1) 
                + (1000 * replace(substr('5.0.0',instr('5.0.0','.') + 1),'.','x'))
                + replace('5.0.0','.','000') % 1000
        ) 
        AND
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        )
    AND 
        (
            SELECT 1000000  * substr('8.5.0',1,instr('8.5.0','.') -1) 
                + (1000 * replace(substr('8.5.0',instr('8.5.0','.') + 1),'.','x'))
                + replace('8.5.0','.','000') % 1000
        ) 
            > 
        (SELECT MAX(model_value) FROM inventory)

ORDER BY model_value
;

SELECT prod_name, 
    CAST (model_value / 1000000 AS TEXT)
        ||'.'
        || CAST((model_value % 1000000) / 1000 AS TEXT)
        ||'.'
        ||CAST(model_value % 1000 AS TEXT) 
        AS model, 
    location 
FROM inventory;