选择按日期分组的数字范围?

时间:2020-04-14 22:45:46

标签: sql sql-server

我有一张桌子,记录着不同地点自来水公司的氯含量分布。首先,我有以下子查询:

SELECT CONCAT(MIN(in_dist.chlorine_mgl), ' - ', MAX(in_dist.chlorine_mgl))
FROM gis_user.BACTISURVEY AS in_dist
    INNER JOIN (SELECT MAX(last_edited_date ) AS max_date, collection_location, sample_type, date_sample_collected
    FROM gis_user.BACTISURVEY 
    GROUP BY date_sample_collected, collection_location, sample_type ) AS tbl ON tbl.collection_location = in_dist.collection_location 
    AND tbl.date_sample_collected = in_dist.date_sample_collected
WHERE samples.district_distribution = in_dist.district_distribution

此子查询有一些条件:

  • 因此,对于我的应用程序中的这些站点,您可以选择编辑条目,但是数据库将这些编辑的存档保存在同一表格中,以“编辑日期”来区分,因此自然地,我需要根据最新的编辑日期时间(由于程序的性质,我希望进行大量修改)
  • 我想获取一组的最小氯气样品值和最大氯气值(该组为district_distribution AND ALSO date_sample_collected)

所以基本上我想要以下内容:

DISTRICT        CHLORINE        DATE COLLECTED
district1       1.2 - 2.6       March 30th 2020
district1       1.4 - 3.2       April 1st 2020
district2       1.6 - 2.4       March 30th 2020

但是我得到类似以下的内容:

DISTRICT        CHLORINE        DATE COLLECTED
district1       1.2 - 3.2       March 30th 2020
district1       1.2 - 3.2       April 1st 2020
district2       1.6 - 2.4       March 30th 2020

因此,向我显示的是,它将在district_distribution组中无论日期如何都采集所有氯气样品,并取其最小值和最大值。我希望它可以区分收集日期和地区。

编辑-

对于以下答案,您的查询是否也涵盖此类情况?

-- Unique Entry 1 (district 1, Type A, AUS, 30th Mar)
    ('district 1', 'type A', 'AUS', '2020-02-30', '2020-04-01', 1.2) --Another row expected min
    ,('district 1', 'type A', 'AUS', '2020-02-30', '2020-04-01', 2.8) --Another row expected max
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-03', 1.1)
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-03', 5.2)
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-05', 1.21) --Expected min
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-05', 1.44) --Expected max

EDIT2: 所以我使用了您的分区和等级建议,这似乎是窍门!我谢谢你!在下面标记为答案。

1 个答案:

答案 0 :(得分:0)

回答dbfiddle.uk

问题解释

  • 有一个表,该表的数据由于存档条目而带有重复的标签,并带有编辑时间戳。
  • 想查找每个last_edit_date列所标识的最新标签数据(区域,收集的日期,类型等)的最大/最小范围

使用的表

declare @bactisurvey table (
    district_distribution varchar(200)
    ,sample_type varchar(100)
    ,collection_location varchar(100)
    ,date_sample_collected datetime
    ,last_edited_date datetime
    ,chlorine_mgl float
);

insert into @bactisurvey 
values
    -- Unique Entry 1 (district 1, Type A, AUS, 30th Mar)
    ('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-01', 1.2)
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-01', 2.8)
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-03', 1.1)
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-03', 5.2)
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-05', 1.21) --Expected min
    ,('district 1', 'type A', 'AUS', '2020-03-30', '2020-04-05', 1.44) --Expected max

    -- Unique Entry 2 (district 2, Type B, AUS, 30th Mar)
    ,('district 2', 'type B', 'AUS', '2020-03-30', '2020-04-01', 1.2)
    ,('district 2', 'type B', 'AUS', '2020-03-30', '2020-04-01', 2.8)
    ,('district 2', 'type B', 'AUS', '2020-03-30', '2020-04-05', 1.11) --Expected min
    ,('district 2', 'type B', 'AUS', '2020-03-30', '2020-04-05', 5.21) --Expected max
    ,('district 2', 'type B', 'AUS', '2020-03-30', '2020-04-05', 1.2)
    ,('district 2', 'type B', 'AUS', '2020-03-30', '2020-04-05', 1.4);

数据显示两个不同的条目,它们在多天内进行了编辑。 我认为修改将提供两个值(一个新的最小值和一个新的最大值,请参见注意事项)。

例如对于第一个唯一条目:

  • 4月1日,原始范围为1.2-2.8。
  • 然后在4月3日使用新的1.1-5.2范围对其进行编辑
  • 最后一次是4月5日,新范围是1.21-1.44(故意将最小值和最大值设为较高以显示我们正在获取最新数据)

查询

;with TopEdits as (
    select 
        edit_num = rank() over (partition by district_distribution, sample_type, collection_location, date_sample_collected order by last_edited_date desc)
        ,district_distribution
        ,sample_type
        ,collection_location
        ,date_sample_collected
        ,last_edited_date
        ,chlorine_mgl
    from @bactisurvey
)
select
    district_distribution
    ,sample_type
    ,collection_location
    ,date_sample_collected
    ,min_chlorine = min(chlorine_mgl)
    ,max_chrloine = max(chlorine_mgl)
from TopEdits
where
    edit_num = 1
group by
    district_distribution
    ,sample_type
    ,collection_location
    ,date_sample_collected

结果与解释

+-----------------------+-------------+---------------------+-------------------------+--------------+--------------+
| district_distribution | sample_type | collection_location | date_sample_collected   | min_chlorine | max_chlorine |
+-----------------------+-------------+---------------------+-------------------------+--------------+--------------+
| district 1            | type A      | AUS                 | 2020-03-30 00:00:00.000 | 1.21         | 1.44         |
+-----------------------+-------------+---------------------+-------------------------+--------------+--------------+
| district 2            | type B      | AUS                 | 2020-03-30 00:00:00.000 | 1.11         | 5.21         |
+-----------------------+-------------+---------------------+-------------------------+--------------+--------------+
  • CTE TopEdits实际上与@bactisurvey表相同,但有一个额外的edit_num列。
  • 此列使用简单的整数对行进行排序,这些行具有相同 district_distributionsample_typecollection_locationdate_sample_collected,并带有最新的修改拥有edit_num=1
  • 有关partition by的更多信息,请参见此Stack Overflow answer
  • 当我们SELECT TopEdits将使用where edit_num = 1进行过滤时,获取每个唯一关键字({{1},district_distributionsample_typecollection_location),然后找到这些行之间的最大值/最小值。
  • NB 我假设每个唯一标签都会进行多次修改,以反映更新的最小值和最大值。

注意事项

我不确定您如何区分“最新最小值”和“最新最大值”值。例如,考虑两个条目:

  • 今天编辑的2020-03值1.5条目
  • 昨天编辑了2020-03年值1.6的条目

新的1.5值取代了以前的最大值1.6,还是新的“最小值”?

我在回答中假设我们实际上对完全相同的date_sample_collected进行了两次编辑,其中一次编辑是新的最小值,而一次编辑是新的最大值。

如果不是这种情况,那么您可以考虑使用last_edit_date而不是row_number(),因为rank() 会增加 row_number()列,无论是否有重复的行。然后,您可以使用edit_num进行过滤,以获取前2行。