Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/229.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在PostgreSQL中查找集合之间的所有行_Php_Sql_Postgresql_Window Functions_Gaps And Islands - Fatal编程技术网

Php 在PostgreSQL中查找集合之间的所有行

Php 在PostgreSQL中查找集合之间的所有行,php,sql,postgresql,window-functions,gaps-and-islands,Php,Sql,Postgresql,Window Functions,Gaps And Islands,我有一个名为tc_fuel的表格,它接收来自GPS车辆的所有燃油相关数据,我想得到最后一个油箱的使用量,以计算整个油箱的MPG,但油箱满100时的读数在2行或3行或更多行后重复多次,因此我的两个100值相邻,我希望能够得到最后一次填充开始和结束ID 到目前为止,我所拥有的: 选择 tc_燃料设备ID, tc_燃料id, 燃料, tc_燃料。使用的燃料, 使用的燃料 从tc_燃料 其中燃料=100 和deviceid=19 按ID订购 描述限制2 然后我进入PHP,检查id差异是否超过100条记录

我有一个名为tc_fuel的表格,它接收来自GPS车辆的所有燃油相关数据,我想得到最后一个油箱的使用量,以计算整个油箱的MPG,但油箱满100时的读数在2行或3行或更多行后重复多次,因此我的两个100值相邻,我希望能够得到最后一次填充开始和结束ID

到目前为止,我所拥有的:

选择 tc_燃料设备ID, tc_燃料id, 燃料, tc_燃料。使用的燃料, 使用的燃料 从tc_燃料 其中燃料=100 和deviceid=19 按ID订购 描述限制2 然后我进入PHP,检查id差异是否超过100条记录,以检查燃油值是否彼此不相邻,但这比应该做的工作要多。我想知道是否有更好的方法

例如,这辆车从一个满油箱开始,然后下降到6%油箱,并进行满油箱加注,我希望能够获取最后一个油箱的所有数据

id    | deviceId  | fuel
------+-----------+-------
1     | 19        | 100  <-- This should be starting point 
2     | 19        | 97  
3     | 19        | 100  
4     | 19        | 96
5     | 19        | 94
6     | 19        | .... (keeps dropping)
7     | 19        | 33
8     | 19        | 31
9     | 19        | 30
10    | 19        | ....
11    | 19        | 6
12    | 19        | 5
13    | 19        | 6    <-- This should be end point (will flag this id as processed)
14    | 19        | 100  <-- Starts all over again in next iteration of the php script
15    | 19        | 99
16    | 19        | 98
17    | 19        | 100
18    | 19        | 99
19    | 19        | 97
20    | 19        | 96
21    | 19        | ....

填充的定义有点模糊。我假设当燃料值上升超过50时,这是一次加油。替换为您选择的数字。看起来一个新的油箱必须从燃油=100开始,尽管这是一个奇怪的情况。我添加了注释-取消注释以激活:

挑选* 从…起 选择*,计数*过滤器,其中按设备填充分区\u id按id排序作为油箱 从…起 挑选* ,fuel-lagfoure,1,0超过按设备划分的分区\u id顺序按id>50 -燃油=100-附加条件? 作为补充 来自tbl sub1 sub2 其中,设备_id=19 和储罐=1; 小提琴

在子查询sub1中,计算每个设备前面的燃料条目与当前的燃料条目之间的差异-使用。值得注意的是,我使用带有3个参数的变量,为缺少的行提供0作为默认值,以覆盖每个分区的第一行。增加超过50表示新的填充

在子查询sub2中,使用另一个窗口函数计算一段时间内的加油次数,从而为每一行分配一个油箱号

在外部选择中,选择您的设备和油箱加注的编号。瞧

如果将device_id=19的条件移动到最里面的suqbquery,则可以删除分区子句。速度更快,通用性更低

关于筛选子句:

仅获取给定设备的最后一个油箱 根据您的评论,定义为上次油箱从20或以下加注到100

我假设稍后的时间点对应于更高的id值。请注意,在并发写负载下,串行列可能会出现转角情况并发症

最简单的方法:颠倒顺序,从底部开始计数:

挑选* 从…起 选择*,计数*过滤器,其中按id描述为油箱的订单加油 从…起 按id DESC=100在订单上选择*,lagfuel,1,0 燃料 首先,我在加油前标记入口

然后,我通过计算这些标记来标记填充:0表示当前填充,1表示上一次填充,依此类推

最后,我在当前填充之前获得最后填充的第一个和最后一个id


将WHERE deviceid=19抛出到最里面的查询中,以仅获取单个设备的数据。

我不是一个优秀的数据库专家,我会循环结果并使用计数器将其相加。当我达到100时,我读取了总数和值的数量。在纯SQL中可能可以做一些事情。。。我想。那是第一次,不是最后一次,对吗?@LaurenzAlbe:最后一次在去年圣诞节的意义上,我把我的心给了你,但就在第二天。。。。现在使用前面的明确说明。虽然在圣诞节之前。。。真的没用这太棒了,我怎么能只搜索最近的填充而不是所有填充?@Ron:定义最近的。最近就像上次一样,它从20到100,例如,因为这将每天运行,我只想要最后的填充,而不是所有的填充
SELECT min(id) AS first_id,
       max(id) AS last_id,
       deviceid
FROM (SELECT id, deviceid, fuel,
             count(*) FILTER (WHERE refilled)
                OVER (PARTITION BY deviceid ORDER BY id DESC) AS filling
      FROM (SELECT id, deviceid, fuel,
                   fuel < lead(luel, 1, 0)
                             OVER (PARTITION BY deviceid ORDER BY id) AS before_fill
            FROM tc_fuel
           ) AS refill
     ) AS fills
WHERE filling = 1
GROUP BY deviceid;