SQL值首次出现的第一个日期

SQL值首次出现的第一个日期,sql,db2,grouping,Sql,Db2,Grouping,我有一张客户表,记录了他们的低、中、高评级历史,每季度进行一次评估 示例表: client_ID rating eff_from 111 high 30.09.2018 111 high 30.06.2018 111 medium 31.03.2018 111 high 31.12.2017 111 high 30.09.2017 111 low 30.06.2017 222 medium 30.09.2018 222 high 30.06.2018 222

我有一张客户表,记录了他们的低、中、高评级历史,每季度进行一次评估

示例表:

client_ID  rating  eff_from
111  high  30.09.2018
111  high  30.06.2018
111  medium  31.03.2018
111  high  31.12.2017
111  high  30.09.2017
111  low  30.06.2017
222  medium  30.09.2018
222  high  30.06.2018
222  high  31.03.2018
222  low  31.12.2017
222  low  30.09.2017
222  medium  30.06.2017
我想获得最新评级的最低有效期。从上表可以看出,客户111为2018年6月30日,客户222为2018年9月30日

诀窍在于,评级可能会从高到中再回到高,因此按客户和评级分组并从日期开始计算最低效率是行不通的——这将导致客户111在2017年9月30日

环境是一个DB2数据库,eff_from字段的格式为date


有什么想法吗

这取决于您使用的SQL方言。在Microsofts Transact-SQL中,我知道存在ROWNUMBER结构,这在这些情况下很有帮助。也许你的大脑中也有类似的东西

示例T-SQL:

SELECT eff_from FROM
(
    SELECT
        *,
        ROW_NUMBER() OVER(PARTITION BY client_ID ORDER BY eff_from ASC) AS RN
    FROM
        EXAMPLE_TABLE
) TABLE_WITH_RN
WHERE
    RN = 1

这取决于您使用的SQL方言。在Microsofts Transact-SQL中,我知道存在ROWNUMBER结构,这在这些情况下很有帮助。也许你的大脑中也有类似的东西

示例T-SQL:

SELECT eff_from FROM
(
    SELECT
        *,
        ROW_NUMBER() OVER(PARTITION BY client_ID ORDER BY eff_from ASC) AS RN
    FROM
        EXAMPLE_TABLE
) TABLE_WITH_RN
WHERE
    RN = 1

您需要行号为的条件排序:

然后,下一步在子查询中使用它并过滤序列:

select *
from ( < query > 
     ) t
where seq = 1;

您需要行号为的条件排序:

然后,下一步在子查询中使用它并过滤序列:

select *
from ( < query > 
     ) t
where seq = 1;

这里有一种解决问题的方法:

CREATE TABLE #T (ClientID INT, RATING VARCHAR (20), eff_From DATE)

INSERT INTO #T VALUES
(111, 'high',  '20180930'  ), 
(111, 'high',  '20180630'  ) ,
(111, 'medium', '20180331' ) ,
(111, 'high',  '20171231'  ) ,
(111, 'high', '20170930'      ) ,
(111, 'low', '20170630'   ); 

WITH CTE AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ClientID ORDER BY  eff_From) AS RowNumb
    FROM #T
)

SELECT C.*, 
      C2.RATING AS C2Rating,
      C2.eff_From AS C2EffFrom,
      CASE WHEN C.RATING <> C2.RATING THEN 1 ELSE 0 END AS RatingChanged 
INTO #T2
FROM CTE AS C
LEFT JOIN CTE AS C2 ON C.RowNumb = C2.RowNumb - 1

SELECT ClientID, MAX (C2EffFrom) AS MaxEffFrom
FROM #T2
WHERE RatingChanged = 1
GROUP BY ClientID

这里有一种解决问题的方法:

CREATE TABLE #T (ClientID INT, RATING VARCHAR (20), eff_From DATE)

INSERT INTO #T VALUES
(111, 'high',  '20180930'  ), 
(111, 'high',  '20180630'  ) ,
(111, 'medium', '20180331' ) ,
(111, 'high',  '20171231'  ) ,
(111, 'high', '20170930'      ) ,
(111, 'low', '20170630'   ); 

WITH CTE AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ClientID ORDER BY  eff_From) AS RowNumb
    FROM #T
)

SELECT C.*, 
      C2.RATING AS C2Rating,
      C2.eff_From AS C2EffFrom,
      CASE WHEN C.RATING <> C2.RATING THEN 1 ELSE 0 END AS RatingChanged 
INTO #T2
FROM CTE AS C
LEFT JOIN CTE AS C2 ON C.RowNumb = C2.RowNumb - 1

SELECT ClientID, MAX (C2EffFrom) AS MaxEffFrom
FROM #T2
WHERE RatingChanged = 1
GROUP BY ClientID
试试这个:

select client_ID, min(eff_from) eff_from
from (
select client_ID, eff_from
, sum(
  case 
  when rating=coalesce(lag(rating) over(partition by client_ID order by eff_from desc), rating) then 0
  else 1
  end
  ) over(partition by client_ID order by eff_from desc) s_
from tab
)
where s_=0
group by client_ID;
试试这个:

select client_ID, min(eff_from) eff_from
from (
select client_ID, eff_from
, sum(
  case 
  when rating=coalesce(lag(rating) over(partition by client_ID order by eff_from desc), rating) then 0
  else 1
  end
  ) over(partition by client_ID order by eff_from desc) s_
from tab
)
where s_=0
group by client_ID;

您使用的是什么数据库,例如MySQL、SQL Server、Oracle?这些生效日期是实际存储为日期,还是存储为文本?您自己尝试过解决这个问题吗?DB2环境eff_from的格式为dates为什么分组结果会选择2017年9月30日作为客户端111?这毫无意义。编辑您的问题并发布您正在使用的查询,以便我们可以帮助您解决问题。如果您这样做:[按客户ID、评级从表名称组中选择客户ID、评级、mineff\u]您将在2017年9月30日获得客户111您使用的数据库是什么,例如MySQL、SQL Server、Oracle?这些生效日期是实际存储为日期,还是存储为文本?您自己尝试过解决这个问题吗?DB2环境eff_from的格式为dates为什么分组结果会选择2017年9月30日作为客户端111?这毫无意义。编辑您的问题并发布您正在使用的查询,以便我们可以帮助您解决问题。如果您这样做:[按客户ID从表_name group中选择客户ID,rating,mineff_,rating]您将获得2017年9月30日,因为客户111DB2是在发布此答案前一秒指定的。您尝试过使用row_number函数,但无法使其工作以解决我的问题…在发布此答案前一秒指定了DB2。我尝试过使用row_number函数,但无法使其工作以解决我的问题。。。