从Firebird DB中选择最新值

时间:2018-11-19 09:44:08

标签: sql firebird greatest-n-per-group

我在Firebird DB中有一个表-请参见picture


我需要了解每个设备的最新位置信息(LOCATION)。每个设备都有唯一的序列号(SERIAL_NUMBER)。最新位置是所有计数器值最高的行(COUNTER1 ... COUNTER6)。 我尝试了以下查询,但必须对其进行补充才能得到我所需要的。不幸的是,我不知道如何修改它。

SELECT LOCATION 
FROM TABLE 
WHERE SERIAL_NUMBER IN (SELECT DISTINCT SERIAL_NUMBER 
                        FROM TABLE) 
ORDER BY COUNTER1, COUNTER2, COUNTER3, COUNTER4, COUNTER5, COUNTER6

从伪答案中,现在已删除:

  

我需要为每一个SERIAL_NUMBER查找最有效的值   为COUNTER1,如果等于COUNTER2,如果等于   COUNTER3 ... COUNTER6。因此,最后将是每个行的一组行   SERIAL_NUMBER,以及最新的位置信息。火鸟版   是2.5设计保持不变,不能更改。没有   表格中的“时间戳”列可在中找到最新的位置信息   直线,所以最大的计数器值代表最大的   当前位置。

1 个答案:

答案 0 :(得分:0)

您在这里:http://sqlfiddle.com/#!17/ff969/1

您需要对Firebird SQL风格进行明显过渡:

  • Firebird不能用一条语句插入很多行。
  • Firebird使用select FIRST(1) .....而不是select .... LIMIT 1
  • 语法

请注意,我是如何依次使用一个SELECT查询的,从构建复杂查询的简单查询开始,先测试每个简单查询(它确实会返回我需要的内容),然后再在它们之上构建更复杂的构造。

在此处阅读有关如何增长查询的过程的更多详细信息:https://stackoverflow.com/a/51398120/976391


PostgreSQL 9.6模式设置

create table tab(
  id /* INTeger NOT NULL AUTO_INCREMENT */ serial primary key,
  ser varchar(20) not null,
  Loc varchar(20) not null,
  c1 integer not null,
  c2 integer not null,
  c3 integer not null,
  c4 integer not null,
  c5 integer not null,
  c6 integer not null
 );

 insert into tab(ser,loc,c1,c2,c3,c4,c5,c6) values
 ('LSE4300308', 'Address 1', 0,0,0, 0,0,0),
 ('LHD4x22414', 'Address 2', 601,504,8, 130,0,0),
 ('LHD4x22414', 'Address 3', 2385,1163,54, 150,0,0),
 ('LSE4300308', 'Address 4', 2209,0,323, 0,0,0),
 ('LSE4300308', 'Address 5', 2257,0,330, 1661,926,0),
 ('LSE4300308', 'Address 6', 2278,0,330, 0,0,0),
 ('LSE4300308', 'Address 7', 2257,0,330, 1661,926,0),
 ('LSE4300308', 'Address 8', 2262,0,330, 1661,926,0),
 ('L873702373', 'Address 9', 12165,25467,1578, 2619,0,0),
 ('L873702373', 'Address A', 12165,25467,1578, 2619,0,0);

 create index t_ser on tab(ser);
 create /* descending */ index t_counters on tab(c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc);

查询1

Select * from tab

Results

| id |        ser |       loc |    c1 |    c2 |   c3 |   c4 |  c5 | c6 |
|----|------------|-----------|-------|-------|------|------|-----|----|
|  1 | LSE4300308 | Address 1 |     0 |     0 |    0 |    0 |   0 |  0 |
|  2 | LHD4x22414 | Address 2 |   601 |   504 |    8 |  130 |   0 |  0 |
|  3 | LHD4x22414 | Address 3 |  2385 |  1163 |   54 |  150 |   0 |  0 |
|  4 | LSE4300308 | Address 4 |  2209 |     0 |  323 |    0 |   0 |  0 |
|  5 | LSE4300308 | Address 5 |  2257 |     0 |  330 | 1661 | 926 |  0 |
|  6 | LSE4300308 | Address 6 |  2278 |     0 |  330 |    0 |   0 |  0 |
|  7 | LSE4300308 | Address 7 |  2257 |     0 |  330 | 1661 | 926 |  0 |
|  8 | LSE4300308 | Address 8 |  2262 |     0 |  330 | 1661 | 926 |  0 |
|  9 | L873702373 | Address 9 | 12165 | 25467 | 1578 | 2619 |   0 |  0 |
| 10 | L873702373 | Address A | 12165 | 25467 | 1578 | 2619 |   0 |  0 |

查询2

Select distinct ser from tab

Results

|        ser |
|------------|
| LSE4300308 |
| L873702373 |
| LHD4x22414 |

查询3

Select /* First(10) */ * from tab
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
  limit 10 

Results

| id |        ser |       loc |   c1 | c2 |  c3 |   c4 |  c5 | c6 |
|----|------------|-----------|------|----|-----|------|-----|----|
|  6 | LSE4300308 | Address 6 | 2278 |  0 | 330 |    0 |   0 |  0 |
|  8 | LSE4300308 | Address 8 | 2262 |  0 | 330 | 1661 | 926 |  0 |
|  5 | LSE4300308 | Address 5 | 2257 |  0 | 330 | 1661 | 926 |  0 |
|  7 | LSE4300308 | Address 7 | 2257 |  0 | 330 | 1661 | 926 |  0 |
|  4 | LSE4300308 | Address 4 | 2209 |  0 | 323 |    0 |   0 |  0 |
|  1 | LSE4300308 | Address 1 |    0 |  0 |   0 |    0 |   0 |  0 |

查询4

Select /* First(1) */ * from tab
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
  limit 1 

Results

| id |        ser |       loc |   c1 | c2 |  c3 | c4 | c5 | c6 |
|----|------------|-----------|------|----|-----|----|----|----|
|  6 | LSE4300308 | Address 6 | 2278 |  0 | 330 |  0 |  0 |  0 |

查询5

Select t1.ser, 
  ( Select /* First(1) */ loc from tab 
    Where ser = t1.ser
    order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
    Limit 1)
From (Select distinct ser from tab) as t1

Results

|        ser |       loc |
|------------|-----------|
| LSE4300308 | Address 6 |
| L873702373 | Address 9 |
| LHD4x22414 | Address 3 |

Firebird 2.1转换。 注意-除非很少运行此查询,否则您最好还是修改数据库结构。不管那里已有什么,您仍然可以添加新的帮助器表,并且仍然可以添加新的triggers以使这些新表自动保持最新。例如,一个单独的附加表“每个序列的最新ID”将使您的生活变得更简单,每次将新行插入位置时都执行update or insert命令。

create table so53371903(
  id integer primary key,
  ser varchar(20) not null,
  Loc varchar(20) not null,
  c1 integer not null,
  c2 integer not null,
  c3 integer not null,
  c4 integer not null,
  c5 integer not null,
  c6 integer not null
 );

 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (0,'LSE4300308', 'Address 1', 0,0,0, 0,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (1,'LHD4x22414', 'Address 2', 601,504,8, 130,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (2,'LHD4x22414', 'Address 3', 2385,1163,54, 150,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (3,'LSE4300308', 'Address 4', 2209,0,323, 0,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (4,'LSE4300308', 'Address 5', 2257,0,330, 1661,926,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (5,'LSE4300308', 'Address 6', 2278,0,330, 0,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (6,'LSE4300308', 'Address 7', 2257,0,330, 1661,926,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (7,'LSE4300308', 'Address 8', 2262,0,330, 1661,926,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (8,'L873702373', 'Address 9', 12165,25467,1578, 2619,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (9,'L873702373', 'Address A', 12165,25467,1578, 2619,0,0)
 ;

 create index t_ser on so53371903(ser);
 create descending index t_counters on so53371903(c1,c2,c3,c4,c5,c6);

Select * from so53371903;

Select distinct ser from so53371903;

Select first(10) * from so53371903
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc;

Select first(1) * from so53371903
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc;

Select t1.ser, 
  ( Select First(1) loc from so53371903
    Where ser = t1.ser
    order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
   )
From (Select distinct ser from so53371903) as t1;

注意:Address 9Address 10在计数器中具有相同的值,Address 5Address 7也是如此。因为在此之间没有“最大计数器”,所以将随机选择“获胜”行。可能今天会有一个获胜者,而在月或年之后运行相同的查询会在这些行中给出不同的结果。