检索具有相同位置的最小和最大存储编号。

huangapple go评论67阅读模式
英文:

Retrieve min and max store number that have the same location

问题

我们的“store”表大致如下:

store_id city_id store_type
1 1 regular
2 1 regular
3 1 regular
50 1 regular
51 1 express
55 1 express
58 1 express
70 1 express
71 2 regular
75 2 regular
78 2 regular
80 2 regular
85 2 regular
90 2 regular
91 1 regular
95 1 regular
97 1 regular
100 1 regular
105 1 regular

我想在SQL Server中创建一个列表,其中两列具有相同的值,因此在我们的store表中,可以执行类似以下的选择:

min_store_id max_store_id city_id store_type
1 50 1 regular
51 70 1 express
71 90 2 regular
91 105 1 regular

然而,问题在于,我们有一个糟糕的store_id系统,因此最后一行和第一行具有相同的值是会在表中发生的情况,而且遗憾的是我们无法更改它。

尝试了类似以下的查询:

SELECT MIN(store_id) OVER (PARTITION BY city_id, store_type) AS min_store_id,
       MAX(store_id) OVER (PARTITION BY city_id, store_type) AS max_store_id,
       city_id,
       store_type
FROM store;

但这不起作用。

英文:

Our "store" table looks something like this:

store_id city_id store_type
1 1 regular
2 1 regular
3 1 regular
50 1 regular
51 1 express
55 1 express
58 1 express
70 1 express
71 2 regular
75 2 regular
78 2 regular
80 2 regular
85 2 regular
90 2 regular
91 1 regular
95 1 regular
97 1 regular
100 1 regular
105 1 regular

I want to create a list in SQL Server that have the same value on 2 columns so in our table store we can make a select that looks something like:

min_store_id max_store_id city_id store_type
1 50 1 regular
51 70 1 express
71 90 2 regular
91 105 1 regular

However the problem is, we hade a bad store_id system so the fact that the last and first row do have the same value is something that will happen in the table, and we sadly cannot change it.

Tried with something like this:

SELECT MIN(store_id) OVER (PARTITION BY city_id, store_type) AS min_store_id,
       MAX(store_id) OVER (PARTITION BY city_id, store_type) AS max_store_id,
       city_id,
       store_type
FROM store;

but it does not work at all.

答案1

得分: 2

这里涉及到一个“缺口和岛屿”问题,你可以使用两个row_numbers之间的差值来创建分组:

with cte as (
  select *, row_number() over (order by store_id) 
          - row_number() over (partition by city_id, store_type order by store_id) as grp
  from store
)
SELECT MIN(store_id) AS min_store_id,
       MAX(store_id) AS max_store_id,
       max(city_id) as city_id,
       max(store_type) as store_type
FROM cte
group by grp

结果:

min_store_id   max_store_id   city_id   store_type
1              50             1         regular
51             70             1         express
71             90             2         regular
91             105            1         regular

演示在这里

英文:

You have a gaps and islands problem here, you could use the difference between two row_numbers approach to create groups :

with cte as (
  select *, row_number() over (order by store_id) 
          - row_number() over (partition by city_id, store_type order by store_id) as grp
  from store
)
SELECT MIN(store_id) AS min_store_id,
       MAX(store_id) AS max_store_id,
       max(city_id) as city_id,
       max(store_type) as store_type
FROM cte
group by grp

Result :

min_store_id	max_store_id	city_id	store_type
1	            50	            1	    regular
51	            70	            1	    express
71	            90	            2	    regular
91	            105	            1	    regular

Demo here

答案2

得分: 2

另一个答案更简洁,但由于我花了时间,我还是要发布。

如前所述,这是一个间隙和岛屿的问题,你需要一种标记要分析的每个组的方法。

在SQL中的解释。

创建表格测试(store_id intcity_id intstore_type varchar12));

插入到测试(store_idcity_idstore_type)中

11'常规'),
21'常规'),
31'常规'),
501'常规'),
511'快递'),
551'快递'),
581'快递'),
701'快递'),
712'常规'),
752'常规'),
782'常规'),
802'常规'),
852'常规'),
902'常规'),
911'常规'),
951'常规'),
971'常规'),
1001'常规'),
1051'常规';

cte1作为
选择*
  - 如果store_type或city_id在order by store_id时发生变化,则是新的组[
  或城市ID <> lagcity_id1city_idoverorder by store_id)时,store_type <> lagstore_type1store_type)的情况时,1否则为0 end Transition
从测试
),cte2作为
  选择*
    - 对转换求和以提供唯一的组ID
    sumTransitionoverorder by store_id[Grouping]
  cte1中选择

选择
  - 计算每个组的所需结果
  最小(store_idmin_store_id
  ,最大(store_idmax_store_id
  city_id
  store_type
cte2中选择
组别
  city_id
  store_type
  [Grouping]
min_store_id排序;

返回

min_store_id max_store_id city_id store_type
1 50 1 regular
51 70 1 express
71 90 2 regular
91 105 1 regular

注意:提供如此所示的DDL+DML使人们更容易回答。

英文:

The other answer is much cleaner, but since I put in the time I'm posting anyway.

As already stated its a gaps-and-islands problem, you need a way to mark each group you want to analyse.

Explanation in the SQL.

create table Test (store_id int, city_id int, store_type varchar(12));
insert into Test (store_id, city_id, store_type)
values
(1,	    1,	&#39;regular&#39;),
(2,	    1,	&#39;regular&#39;),
(3,	    1,	&#39;regular&#39;),
(50,	1,	&#39;regular&#39;),
(51,	1,	&#39;express&#39;),
(55,	1,	&#39;express&#39;),
(58,	1,	&#39;express&#39;),
(70,	1,	&#39;express&#39;),
(71,	2,	&#39;regular&#39;),
(75,	2,	&#39;regular&#39;),
(78,	2,	&#39;regular&#39;),
(80,	2,	&#39;regular&#39;),
(85,	2,	&#39;regular&#39;),
(90,	2,	&#39;regular&#39;),
(91,	1,	&#39;regular&#39;),
(95,	1,	&#39;regular&#39;),
(97,	1,	&#39;regular&#39;),
(100,	1,	&#39;regular&#39;),
(105,	1,	&#39;regular&#39;);
with cte1 as (
select *
-- If the store_type or the city_id changes its a new group[
, case when store_type &lt;&gt; lag(store_type, 1, store_type) over (order by store_id)
or city_id &lt;&gt; lag(city_id, 1, city_id) over (order by store_id) then 1 else 0 end Transition
from Test
), cte2 as (
select *
-- Sum the transitions to provide a unique group id
, sum(Transition) over (order by store_id) [Grouping]
from cte1
)
select
-- Calculate desired results per group
min(store_id) min_store_id
, max(store_id) max_store_id
, city_id
, store_type
from cte2
group by
city_id
, store_type
, [Grouping]
order by min_store_id;

Returns

min_store_id max_store_id city_id store_type
1 50 1 regular
51 70 1 express
71 90 2 regular
91 105 1 regular

Note: Providing the DDL+DML as shown here makes it much easier for people to answer.

db<>fiddle

huangapple
  • 本文由 发表于 2023年6月1日 15:47:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379717.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定