SQLITE查询-要检索两个版本之间的所有版本?

时间:2019-07-16 03:38:51

标签: sql python-3.x sqlite version

sqlite表由以下属性组成:

|Versions (TEXT)|
| "2.73.8"      | 
| "3.6.4 "      | 
| "3.9.11"      | 

以此类推。

我想从查询中给定的两个版本之间的表中检索所有版本。例如:在2.9.10和3.7.10之间。

我找不到任何sqlite函数直接查询此函数。我使用Substring(SUBSTR)进行拆分以获取各个数字,然后可以将这些数字与表中存在的数字进行比较。我这样做很成功,但是我可以找到一种查询方法来检索两个版本集之间的所有版本。

create table prod(version varchar);

insert into prod values('2.7.5');
insert into prod values('2.7.4');
insert into prod values('2.0.0');
insert into prod values('22.73.55');
insert into prod values('22.17.54');
insert into prod values('22.10.06');
insert into prod values('3.7.5');
insert into prod values('3.4.5');
insert into prod values('3.7.6');

查询以获取低于或等于以下所有版本:“ 3.50.6”(使用嵌套的“ case when”):



SELECT * from prod
Where version IN ( SELECT 
    CASE WHEN (CAST(substr(version,0,instr(version,'.')) as integer)=3)
         THEN 
            CASE WHEN (cast(SUBSTR(SUBSTR(version, INSTR(version, '.')),1,INSTR(SUBSTR(version, INSTR(version, '.') + 1), '.') - 1) as float)< 0.50 )
                 THEN
                    version
                 ELSE
                    CASE WHEN (cast(SUBSTR(SUBSTR(version, INSTR(version, '.')),1,INSTR(SUBSTR(version, INSTR(version, '.') + 1), '.') - 1) as float)=0.50)
                         THEN
                             CASE WHEN (CAST(replace(version, rtrim(version, replace(version, '.', '')), '')AS INTEGER)<=6)
                                  THEN version

END  END END END FROM prod);


请为我提供一种查询以检索表中两组版本之间的所有版本的方法。

2 个答案:

答案 0 :(得分:0)

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

WITH 
  /* SELECTION parameters */
  parm(p1,p2) AS (SELECT '3.4.5', '22.10.6' /*<<<<<<<<<<<<< Versions to check against lower first*/),
    /* Parse 1, 1st value of each and the rest for parse2 */
    pv1(parmv1,rest4p2,parm2v1,rest4p22) AS (
        SELECT 
            CAST(substr(p1,1,instr(p1,'.')-1) AS INTEGER),
            substr(p1,instr(p1,'.')+1), 
            CAST(substr(p2,1,instr(p2,'.')-1) AS INTEGER),
          substr(p2,instr(p2,'.')+1)    
        FROM parm
        ),
    /* Parse 2 extra 2 values retrieved for each parameter */
    pv2(parmv2,parmv3,parm2v2,parm2v3) AS (
        SELECT 
            CAST(substr(rest4p2,1,instr(rest4p2,'.')-1) AS INTEGER),
            CAST(substr(rest4p2,instr(rest4p2,'.')+1) AS INTEGER),
            CAST(substr(rest4p22,1,instr(rest4p22,'.')-1) AS INTEGER),
            CAST(substr(rest4p22,instr(rest4p22,'.')+1) AS INTEGER)
    FROM pv1),
    /* calculate the lower and upper values to be checked against for the BETWEEN clause */
    finalp(lower,higher) AS (
        SELECT 
            (parmv1 * 1000 * 1000) + (SELECT (parmv2 * 1000) + parmv3 FROM pv2),
            (parm2v1 * 1000 * 1000) + (SELECT (parm2v2 * 1000) + parm2v3 FROM pv2) 
        FROM pv1),

    /* Parse 1 for the actual data gets the 1st part of the version and the rest of the version */  
    v1(v1rowid,vpart1,rest4v2) AS (SELECT rowid, CAST(substr(version,1,instr(version,'.')-1) AS INTEGER),substr(version,instr(version,'.')+1)  FROM prod),
    /* Parse 2 for the actual data gets the 2nd and third parts */
    v2(v2rowid,vpart2,vpart3) AS (SELECT v1rowid, CAST(substr(rest4v2,1,instr(rest4v2,'.')+1) AS INTEGER),CAST(substr(rest4v2,instr(rest4v2,'.')+1) AS INTEGER) FROM v1)

SELECT version
FROM v1 
    JOIN v2 ON v1rowid = v2rowid /* join the 2nd and third parts with the 1st */
    JOIN prod ON prod.rowid = v1rowid /* also join the original data for the original version */ 
    JOIN finalp ON 1 = 1 /* joint the upper and lower values */
WHERE 
    (vpart1 * 1000 * 1000) + (vpart2 * 1000) + vpart3 /* do the same calculation used for the upper and lower parameters */ 
    BETWEEN lower AND higher
; 

以上结果为:-

enter image description here

并使用:-

.... (SELECT '3.4.5', '22.10.06' /*<<<<<<<<<<<<< Versions to check against lower first*/) ...

以及:-

.... (SELECT '3.4.5', '22.10.6' /*<<<<<<<<<<<<< Versions to check against lower first*/) ....

- .6 而不是 .06 (即忽略前导0)

结果:-

enter image description here

  • 这还将检查边界命中,即选择了3.4.5和20.10.06。

答案 1 :(得分:0)

我假设版本值的3个部分中的每个部分最多3个数字。
将版本值转换为数字以使其具有可比性的最简单方法是:将第一部分乘以1000000,第二部分乘以1000,然后将其加3d部分。
在代码中:

1000000 * replace(version, '.', 'x') +
1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
replace(version, '.', '000') % 1000 number

如果执行:

select 
  version,
  1000000 * replace(version, '.', 'x') +
  1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
  replace(version, '.', '000') % 1000 numericversion
from prod

您得到:

| version  | numericversion  |
| -------- | --------------  |
| 2.7.5    |  2007005        |
| 2.7.4    |  2007004        |
| 2.0.0    |  2000000        |
| 22.73.55 | 22073055        |
| 22.17.54 | 22017054        |
| 22.10.06 | 22010006        |
| 3.7.5    |  3007005        |
| 3.4.5    |  3004005        |
| 3.7.6    |  3007006        |

因此,要获取2.9.10和3.7.10之间的所有版本,请执行以下操作:

with 
  cte1 as (
    select
      1000000 * replace('2.9.10', '.', 'x') +
      1000 * replace(substr('2.9.10', instr('2.9.10', '.') + 1), '.', 'x') +
      replace('2.9.10', '.', '000') % 1000 numericversion  
  ),
  cte2 as (
    select
      1000000 * replace('3.7.10', '.', 'x') +
      1000 * replace(substr('3.7.10', instr('3.7.10', '.') + 1), '.', 'x') +
      replace('3.7.10', '.', '000') % 1000 numericversion  
  ),
  versions as (
    select 
      version, 
      1000000 * replace(version, '.', 'x') +
      1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
      replace(version, '.', '000') % 1000 numericversion
    from prod  
  )  
select version from versions
where numericversion between 
  (select numericversion from cte1) and (select numericversion from cte2)

第一个CTE返回数值2.9.10,第二个CTE返回数值3.7.10,而3d返回表中所有版本的数值。
最后,查询会比较数字版本。
请参见demo
结果:

| version |
| ------- |
| 3.7.5   |
| 3.4.5   |
| 3.7.6   |

或者没有CTE,可以将2个版本硬编码为数字:

select version from prod
where 
  1000000 * replace(version, '.', 'x') +
  1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
  replace(version, '.', '000') % 1000 
  between 2009010 and 3007010

请参见demo
或者:

select version from prod
where 
  1000000 * replace(version, '.', 'x') +
  1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
  replace(version, '.', '000') % 1000 
  between 
    1000000 * replace('2.9.10', '.', 'x') +
    1000 * replace(substr('2.9.10', instr('2.9.10', '.') + 1), '.', 'x') +
    replace('2.9.10', '.', '000') % 1000
    and
    1000000 * replace('3.7.10', '.', 'x') +
    1000 * replace(substr('3.7.10', instr('3.7.10', '.') + 1), '.', 'x') +
    replace('3.7.10', '.', '000') % 1000 

请参见demo