Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.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
SQL更改计数器-检查第一个和最后一个值_Sql_Postgresql - Fatal编程技术网

SQL更改计数器-检查第一个和最后一个值

SQL更改计数器-检查第一个和最后一个值,sql,postgresql,Sql,Postgresql,我一直在尝试检查一个用户id从数字4、5或6开始更改到之后结束的总次数。因此,在本例中,我们将为ID 62360的4对4计数器添加+1,为ID 61874的4对5计数器添加+1 数据表: ID Before After Date 61874 4 6 2021-06-04 14:53:25 61874 6 5 2021-06-04 14:55:30 62360 4 6 2021-06-03 14:18:31 62360 6 4 2021-06

我一直在尝试检查一个用户id从数字4、5或6开始更改到之后结束的总次数。因此,在本例中,我们将为ID 62360的4对4计数器添加+1,为ID 61874的4对5计数器添加+1

数据表:

ID  Before  After   Date
61874   4   6   2021-06-04 14:53:25
61874   6   5   2021-06-04 14:55:30
62360   4   6   2021-06-03 14:18:31
62360   6   4   2021-06-03 14:18:33
62360   4   6   2021-06-03 14:18:37
62360   6   4   2021-06-03 14:18:39
期望输出:

Changes Tot.Count 
4 to 4  1
4 to 5  1
4 to 6  0
5 to 4  0
5 to 5  0
5 to 6  0
6 to 4  0
6 to 5  0
6 to 6  0
我在获取上面的输出时遇到了问题,该输出将更改列表化,如更改/计数表中记录的那样

我只对每个身份证的前一个案例和后一个案例的计数感兴趣,但在起草此文件时遇到了困难。我认为它必须是一个分组、CTE和滞后函数的组合

select CASE
           WHEN () THEN '4 to 4'
           WHEN () THEN '4 to 5'
           WHEN () THEN '4 to 6'
           WHEN () THEN '5 to 4'
           WHEN () THEN '5 to 5'
           WHEN () THEN '5 to 6'
           WHEN () THEN '6 to 4'
           WHEN () THEN '6 to 5'
           WHEN () THEN '6 to 6'
        end as changes,
       count(*) as Count_Changes 
from data group by 2;  

如果可能的话,python脚本可以这样做,但不确定如何将case语句作为python函数实现

如果我理解正确,您希望每个ID都有before列的第一个值和after列的最后一个值。这里的first_值和last_值将对您有所帮助

首先,我们将使用以下查询获取每个组的值:

select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab
with cte as (
select *, 
case when fv=4 and lv=4 then '4 to 4' 
 when fv=4 and lv=5 then '4 to 5'
 when fv=4 and lv=6 then '4 to 6'
 when fv=5 and lv=4 then '5 to 4'
 when fv=5 and lv=5 then '5 to 5'
 when fv=5 and lv=6 then '5 to 6'
 when fv=6 and lv=4 then '6 to 4'
 when fv=6 and lv=5 then '6 to 5'
 when fv=6 and lv=6 then '6 to 6'
end "range" from (
select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab

)

select tab.col1 "Changes", count("range") "Tot.Count" from (
values('4 to 4'),('4 to 5'),('4 to 6'),('5 to 4'),('5 to 5'),('5 to 6'),('6 to 4'),('6 to 5'),('6 to 6')
) tab(col1) 
left join cte on tab.col1=cte."range"

group by 1 order by 1
上述查询将为您提供如下输出:

61874   4   5
62360   4   4

要获得准确的输出,请使用以下查询:

select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab
with cte as (
select *, 
case when fv=4 and lv=4 then '4 to 4' 
 when fv=4 and lv=5 then '4 to 5'
 when fv=4 and lv=6 then '4 to 6'
 when fv=5 and lv=4 then '5 to 4'
 when fv=5 and lv=5 then '5 to 5'
 when fv=5 and lv=6 then '5 to 6'
 when fv=6 and lv=4 then '6 to 4'
 when fv=6 and lv=5 then '6 to 5'
 when fv=6 and lv=6 then '6 to 6'
end "range" from (
select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab

)

select tab.col1 "Changes", count("range") "Tot.Count" from (
values('4 to 4'),('4 to 5'),('4 to 6'),('5 to 4'),('5 to 5'),('5 to 6'),('6 to 4'),('6 to 5'),('6 to 6')
) tab(col1) 
left join cte on tab.col1=cte."range"

group by 1 order by 1

如果我理解正确,您需要每个ID的before列的第一个值和after列的最后一个值。这里的first_值和last_值将帮助您

首先,我们将使用以下查询获取每个组的值:

select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab
with cte as (
select *, 
case when fv=4 and lv=4 then '4 to 4' 
 when fv=4 and lv=5 then '4 to 5'
 when fv=4 and lv=6 then '4 to 6'
 when fv=5 and lv=4 then '5 to 4'
 when fv=5 and lv=5 then '5 to 5'
 when fv=5 and lv=6 then '5 to 6'
 when fv=6 and lv=4 then '6 to 4'
 when fv=6 and lv=5 then '6 to 5'
 when fv=6 and lv=6 then '6 to 6'
end "range" from (
select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab

)

select tab.col1 "Changes", count("range") "Tot.Count" from (
values('4 to 4'),('4 to 5'),('4 to 6'),('5 to 4'),('5 to 5'),('5 to 6'),('6 to 4'),('6 to 5'),('6 to 6')
) tab(col1) 
left join cte on tab.col1=cte."range"

group by 1 order by 1
上述查询将为您提供如下输出:

61874   4   5
62360   4   4

要获得准确的输出,请使用以下查询:

select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab
with cte as (
select *, 
case when fv=4 and lv=4 then '4 to 4' 
 when fv=4 and lv=5 then '4 to 5'
 when fv=4 and lv=6 then '4 to 6'
 when fv=5 and lv=4 then '5 to 4'
 when fv=5 and lv=5 then '5 to 5'
 when fv=5 and lv=6 then '5 to 6'
 when fv=6 and lv=4 then '6 to 4'
 when fv=6 and lv=5 then '6 to 5'
 when fv=6 and lv=6 then '6 to 6'
end "range" from (
select 
distinct on (id)
id,
first_value(before) over (partition by id order by date_) "fv",
last_value(after) over (partition by id order by date_  RANGE BETWEEN 
            UNBOUNDED PRECEDING AND 
            UNBOUNDED FOLLOWING) "lv" 
from data ) tab

)

select tab.col1 "Changes", count("range") "Tot.Count" from (
values('4 to 4'),('4 to 5'),('4 to 6'),('5 to 4'),('5 to 5'),('5 to 6'),('6 to 4'),('6 to 5'),('6 to 6')
) tab(col1) 
left join cte on tab.col1=cte."range"

group by 1 order by 1

我想我会有点不同的处理方式。不需要在一行中实际获取第一个before和最后一个after值。也不需要列出前后值的所有可能组合,因为它们可以生成

您可以在最终查询中生成值的组合。您可以在单独的查询中获取第一个before和最后一个after,然后将它们加入:

with ba (val) as (
      values (4), (5), (6)
     )
select ba_before.val as from_val, ba_after.val as after_val, count(a.id),
       ba_before.val || ' to ' || ba_after.val as string_version
from ba ba_before cross join
     ba ba_after left join
     (select distinct on (id) id, before
      from data
      order by id, date asc
     ) b
     on b.before = ba_before.val left join
     (select distinct on (id) id, after
      from data
      order by id, date desc
     ) a
     on a.id = b.id and
        a.after = ba_after.val
group by 1, 2;
他是一把小提琴

如果愿意,您可以直接从数据中生成ba列表:

with ba as (
      select distinct val
      from data cross join lateral
           (values (before), (after)) v(val)
     )

注意,这也可以为子查询使用id、date asc/id、date desc上的索引。如果您使用大量数据,这将大大提高性能。

我想我会以不同的方式处理这一问题。不需要在一行中实际获取第一个before和最后一个after值。也不需要列出前后值的所有可能组合,因为它们可以生成

您可以在最终查询中生成值的组合。您可以在单独的查询中获取第一个before和最后一个after,然后将它们加入:

with ba (val) as (
      values (4), (5), (6)
     )
select ba_before.val as from_val, ba_after.val as after_val, count(a.id),
       ba_before.val || ' to ' || ba_after.val as string_version
from ba ba_before cross join
     ba ba_after left join
     (select distinct on (id) id, before
      from data
      order by id, date asc
     ) b
     on b.before = ba_before.val left join
     (select distinct on (id) id, after
      from data
      order by id, date desc
     ) a
     on a.id = b.id and
        a.after = ba_after.val
group by 1, 2;
他是一把小提琴

如果愿意,您可以直接从数据中生成ba列表:

with ba as (
      select distinct val
      from data cross join lateral
           (values (before), (after)) v(val)
     )

注意,这也可以为子查询使用id、date asc/id、date desc上的索引。如果您正在处理大量数据,这可能会大大提高性能。

不清楚您的第一个示例是给定的数据表还是期望的结果,请澄清。如果是数据表,只需选择concatto_charbefore、'999'、'to',to charafter、'999'作为更改,将*作为concatto_charbefore、'999'、'to',to charafter、'999'从任何组中的计数。感谢@chrismourer的反馈。事实上,第一个示例是给定的数据表,我试图从中获得上述CTE的计数/分组。不清楚您的第一个示例是给定的数据表还是期望的结果,请澄清。如果是数据表,只需选择concatto_charbefore、'999'、'to',to charafter、'999'作为更改,将*作为concatto_charbefore、'999'、'to',to charafter、'999'从任何组中的计数。感谢@chrismourer的反馈。事实上,第一个示例是给定的数据表,我正试图从中获得上述CTE的计数/分组