【问题标题】:Serial number auto generation序列号自动生成
【发布时间】:2019-01-10 10:26:11
【问题描述】:

在自动生成序列号时面临问题。

我怎样才能以正确的方式使用row_number(),或者有什么替代方法可以达到预期的效果?

注意:我想在不使用CASE的情况下编写查询。

SELECT 
 row_number() over (order by COALESCE(legs.sta, legs.eta) ASC) sno,
 legs.Flight_ID flightId,
 legs.flight,
 legs.flightDate           
FROM Flt_OperativeFlight_Legs LEG
ORDER BY COALESCE(legs.sta, legs.eta) ASC

当前结果:

+------+--------+-------------------------+
| sno  | flight |       flightDate        |
+------+--------+-------------------------+
|    1 | 3K0722 | 2019-01-08 17:10:00.000 |
|    2 | 3K0722 | 2019-01-08 20:20:00.000 |
|    3 | 3K0723 | 2019-01-09 17:10:00.000 |
|    4 | 3K0724 | 2019-01-10 20:20:00.000 |
+------+--------+-------------------------+

预期结果:

+------+--------+-------------------------+
| sno  | flight |       flightDate        |
+------+--------+-------------------------+
|    1 | 3K0722 | 2019-01-08 17:10:00.000 |
|      |        | 2019-01-08 20:20:00.000 |
|    2 | 3K0723 | 2019-01-09 17:10:00.000 |
|    3 | 3K0724 | 2019-01-10 20:20:00.000 |
+------+--------+-------------------------+

【问题讨论】:

  • 隔天id是+1是什么意思?
  • 看起来更像是您想要DENSE_RANK 而不是ROW_NUMBER,但是,为什么第二行没有s.noflt_idflight 的值?我猜这是一个表示的事情,但如果是这样的话,你应该在你的表示层而不是数据引擎中处理它。
  • 为什么是Coalesce?为什么不例如 cast(FlightDate as date) ?您的预期结果按 FlightDate 的日期部分排序和排名
  • @Larnu 因为同一个航班。
  • @PanagiotisKanavos 是的。可以的。

标签: sql sql-server tsql group-by rowcount


【解决方案1】:

您可以尝试在子查询中使用ROW_NUMBER窗口函数,然后使用DENSE_RANK窗口函数创建no列,CASE WHEN表达式得到rn = 1行。

SELECT (CASE WHEN rn = 1 THEN DENSE_RANK() over(order by flight) END) no,
       (CASE WHEN rn = 1 THEN flt_id END) flt_id,
       (CASE WHEN rn = 1 THEN flight END) flight,
       flightDate
FROM 
(
    SELECT *,ROW_NUMBER() OVER(PARTITION BY flt_id,flight ORDER BY flightDate) rn
    FROM Flt_OperativeFlight_Legs 
) t1

sqlfiddle

【讨论】:

  • 期待结果而不使用CASE
  • @SantoshJadi 你有什么理由想要在不使用CASE的情况下获得结果
【解决方案2】:

你需要其他row_number()

SELECT DENSE_RANK() OVER (ORDER BY flt_id, flight) AS Sr,
       (CASE WHEN Seq = 1 
             THEN flightId
        END) AS Flight_ID,
       (CASE WHEN Seq = 1 
             THEN flight
        END) AS flight, flightDate
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY Flight_ID, flight ORDER BY flightDate) AS Seq,
             legs.Flight_ID flightId, legs.flight, legs.flightDate
      FROM Flt_OperativeFlight_Legs LEG
     ) l;

【讨论】:

  • 期待结果而不使用CASE
【解决方案3】:

您可以使用DENSE_RANK 代替ROW_NUMBER

SELECT 
 DENSE_RANK() over (order by COALESCE(legs.sta, legs.eta, legs.ata) ASC) as "s.no",
 legs.Flight_ID flightId
 ,legs.flight
 ,legs.flightDate
FROM Flt_OperativeFlight_Legs LEG
ORDER BY COALESCE(legs.sta, legs.eta, legs.ata) ASC

【讨论】:

    【解决方案4】:

    请参考以下解决方案,清空我需要使用 CASE 表达式的重复数据

    在 CTE 表达式中,我将 Row_Number 和 Dense_Rank 函数与 Partition By clause 结合使用

    ;with cte as (
        select
            ROW_NUMBER() over (order by flight, flightDate) as num,
            DENSE_RANK() over (order by flight) as [no],
            ROW_NUMBER() over (partition by flight order by flightDate) as rn,
            flight,
            flightDate
        from Flt_OperativeFlight_Legs legs
    )
    select
        case when rn > 1 then null else [no] end as [no],
        case when rn > 1 then null else flight end as flight,
        flightDate
    from cte
    order by num
    

    输出如下

    【讨论】:

    • 期待结果而不使用CASE
    • 是的,我读过。但无法理解背后的原因。要转换重复值,需要 CASE 语句。否则将看不到 NULL 或空字符串值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 2010-12-29
    • 2021-12-03
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 2012-11-23
    相关资源
    最近更新 更多