【问题标题】:select up-to-date values from Firebird DB从 Firebird DB 中选择最新值
【发布时间】:2018-11-19 09:44:07
【问题描述】:

我在 Firebird DB 中有一张表 - 请参阅


我需要知道每台设备的最新位置信息 (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 并且如果等于 计数器 3...计数器 6。所以最后它将是每个行的一组行 SERIAL_NUMBER 包含最新的位置信息。火鸟版。 是 2.5 设计保持原样,不能更改。没有 在表中的时间戳列中查找最新的位置信息 一条直线,所以最大的计数器值代表最 当前位置。

【问题讨论】:

  • 您能解释一下“最高的所有计数器值”是什么意思吗?如果缺少第 204750 行,LSE3400308 的正确位置是什么?为什么?
  • 请做出理想的查询输出,以便我们理解逻辑。
  • 请解释什么是“设备”。我没有在表格中看到它。
  • 您使用的是哪个 Firebird 版本?
  • 请指定相关的 Firebird 版本,并提供示例数据和预期输出为 text。另外,“它必须得到补充才能得到我需要的东西”是什么意思

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


【解决方案1】:

给你: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 也是如此。因为在那之间没有“最大计数器” - “获胜”行将被随机选择。可能今天会有一个获胜者,而在一个月或一年之后运行相同的查询会在这些行中给出不同的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 2014-02-02
    • 2015-06-24
    • 2023-03-11
    相关资源
    最近更新 更多