代码之家  ›  专栏  ›  技术社区  ›  WAQ

从select语句中的字母表示中获取一周中天数的字符串表示

  •  -1
  • WAQ  · 技术社区  · 2 年前

    我有一个数据库字段,它定义了车辆的操作天数,如下所示。

    操作日期:1234567(1表示周一,2表示周二,……,7表示周日)。。

    对于不同的车辆,运营日可以是13412367346(或任何组合)。

    对于这个给定的输入,我如何获得下面这样的字符串表示。

    输入:Operation_days:1234567
    输出:天:M、T、W、T、F、S、S

    我尝试过使用stuff运算符进行选择,但我不确定如何在每个字段上迭代。。

    我也尝试过CASE WHEN THEN END语句,但硬代码的排列太多,所以我想到了一个通用的select语句,它可以根据任何输入组合返回字符串表示。

    0 回复  |  直到 2 年前
        1
  •  2
  •   Isolated    2 年前

    正如上面众多评论所指出的,一封信不适用于此,因为你无法区分周二与周四或周六与周日。您需要使用多个字母,这排除了诸如 translate() 。这是一个使用 replace() 函数,这样你就可以选择你觉得每天最适合的字母。长度可能会有所不同。

    create table schedule (
      car_id integer, 
      operation_days varchar(7)
      );
    
    insert into schedule values 
    (1, 1234567), 
    (2, 134), 
    (3, 12367), 
    (4, 346);
    
    select car_id, 
      substring(s_days, 1, (len(s_days)-1)) as car_schedule
    from (
    select car_id, 
     replace(replace(replace(replace(replace(replace(replace(operation_days, 
      '1', 'M,'), 
      '2', 'T,'), 
      '3', 'W,'),
      '4', 'Th,'), 
      '5', 'F,'), 
      '6', 'Sa,'),
      '7', 'Su,') as s_days
    from schedule
      )z
    
    car_id 车辆时间表
    1. M、 T、W、Th、F、Sa、Su
    2. M、 W,Th
    3. M、 T、W、Sa、Su
    4. W、 Th,Sa

    fiddle

    更新

    或者,正如马丁建议的那样,在日期前加一个逗号,这样就不需要计算长度了。。。

    select car_id, 
      SUBSTRING(
     replace(replace(replace(replace(replace(replace(replace(operation_days, 
      '1', ',M'), 
      '2', ',T'), 
      '3', ',W'),
      '4', ',Th'), 
      '5', ',F'), 
      '6', ',Sa'),
      '7', ',Su'), 2, 8000) as s_days
    from schedule
    
        2
  •  2
  •   Patrick Hurst    2 年前

    以下是DDL/DML示例:

    DECLARE @Table TABLE (ID INT IDENTITY, OperationDays VARCHAR(7));
    INSERT INTO @Table (OperationDays) VALUES
    ('1357'),('1234567'),('23456');
    

    当试图回答问题时,这真的很有帮助。

    正如其他人所指出的,使用 SMTWTFS 不是个好主意。然而,多年前就已经解决了这一问题: NMTWRFS 表示一周中的所有日子 N 代替苏 n 天,以及 R 星期四 r 星期四。

    考虑:

    ;WITH days AS (
    SELECT ID, OperationDays, SUBSTRING(OperationDays,1,1) AS Chr, 1 AS ChrN
      FROM @Table t
    UNION ALL
    SELECT ID, OperationDays, SUBSTRING(OperationDays,ChrN+1,1), ChrN+1
      FROM days
     WHERE chr < LEN(OperationDays)
    )
    
    SELECT ID, STRING_AGG(DayV,',') AS CarSchedule
      FROM days d
        INNER JOIN (SELECT DayI, DayV FROM (VALUES (1,'N'),(2,'M'),(3,'T'),(4,'W'),(5,'R'),(6,'F'),(7,'S')) a(DayI, DayV)) a
          ON d.Chr = a.DayI
     GROUP BY ID;
    

    假设您可以访问 STRING_AGG 。这还有一个优点,即在表中创建替换的日期行(在这种情况下为values语句)。

    身份证件 CarSchedule
    1. N、 T,R
    2. N、 M、T、W、R、F、S
    3. M、 T、W、R
        3
  •  1
  •   Stu    2 年前

    另一个选项是将天数拆分为行(它们应该在哪里),连接到映射表表达式,然后重新聚合,显然映射的日期值可以是您选择的任何值:

    /*Populate some test data*/
    select * into t 
    from(values 
        (1, '1234567'), 
        (2, '134'), 
        (3, '12367'), 
        (4, '346'))v(VehicleId, Operation_days)
    
    select VehicleId, String_Agg(v.dayval, ',')
    from t
    join(values(1),(2),(3),(4),(5),(6),(7))n(n) on n <= Len(Operation_days)
    cross apply(values(Substring(Operation_days, n, 1)))d(daynum)
    join(values('1', 'Mon'),('2', 'Tue'),('3', 'Wed'),('4', 'Thu'),
               ('5', 'Fri'),('6', 'Sat'),('7', 'Sun')
        )v(daynum, dayval) on v.daynum = d.daynum
    group by VehicleId;
    

    请参阅 demo fiddle