如何使用选择值表从列值动态选择后缀值

时间:2015-01-19 22:49:03

标签: mysql sql-server casting

主要问题:我无法在MS Sql中重新创建两个MySQL语句 - 因为MS SQL例如没有像'1g'那样将值转换为整数值1,尽管MySQL似乎使用我创建的MySql语句。

我的情况: 我有一个表中的数据列,其中包含数字+后缀字符值的混合。我有另一个关于允许的后缀值的信息表。我正在努力完成这些事情:

  1. 选择包含某些后缀值和相关数据字段值的primary_data行(使用外部表和where子句)
  2. 将清理后的数字值显示为整数(擦除后缀)以进行排序
  3. 在10列的行中返回26到1000之间的“缺失”数字列表(每列代表0-9,数字1-25始终不可用)
  4. 已经拍摄的数字(“不可用”)用波浪号'〜'表示,那些“可用”在各自的列中显示为数字

    - 项目3&上面的4不是问题但是我需要1& 2

  5. 明确的数据限制:

    • 没有数字(数字部分)将超出(1-999)
    • 的范围
    • 允许的后缀值全部包含在外部表中

    我尝试了什么:

    我有一个MySQL版本可以按我想要的方式工作,但我需要将其转换为MS Sql。当我尝试手动将MySQL语句转换为MS Sql时,我无法转换为int错误(即将'1g'转换为int)。我将下面提到的每个数据表的MS SQL实例作为MySQL模式,但我无法弄清楚如何将MySQL语句重新创建到MS SQL中,因为数据会发生转换错误。

    重要的问题是[primary_data]。[No]字段包含不同的长度后缀值(所以我不能只看最后一个结束字符。)

    我在寻找什么:

    我真正想要的是一种简单的方法,使用在另一个表中找到的值(即[suffix_values]。[allowed_values],从表中以“喜欢”的方式选择列(即[primary_data]。[No])。 ])。或者,我想了解如何将MySQL视图和结果查询重新创建为有效的MS Sql语句。


    示例MySQL良好结果 - 剪辑显示数字20-99(csv):

    Ten's,0,1,2,3,4,5,6,7,8,9
    20's,~,~,~,~,~,~,~,~,28,~
    30's,~,~,~,33,34,~,~,~,~,39
    40's,~,~,~,43,~,~,46,47,~,49
    50's,50,51,~,~,~,~,~,~,58,59
    60's,60,61,62,63,~,~,~,67,68,69
    70's,~,71,~,~,~,~,76,~,78,79
    80's,80,81,82,83,84,85,86,87,~,~
    90's,90,91,92,~,~,95,~,97,98,99
    

    示例数据: primary_data (模拟csv数据)

    Chapter,No,Additional1,Additional2,Additional8
    South,96,,Name 1,2014
    South,75od,One Day,Name 2,2014
    South,88ee,South,Name 3,2014
    South,77g,South,Name 4,2014
    South,32g,South,Name 5,2014
    South,34od,One Day,Name 6,2014
    South,51ot,Old Timers,Name 7,2014
    South,35e,South,Name 8,2014
    South,42g,South,Name 9,2014
    

    注意到上面的示例行,预期的结果是包含“g”,“e”,“ee”的行会在它们各自的数字桶中产生波浪号。所有其他数字将显示在各自的桶中。

    示例数据: 后缀_值:(csv)

    Id,Chapter,Suffix,IsEnabled
    1,South,g,1
    2,Sierra,s,1
    3,Bay,b,1
    4,Reno,r,1
    5,Valley,v,1
    6,One Day,od,0
    7,1st Eval,e,1
    8,2nd Eval,ee,1
    9,Old Timers,ot,0
    

    表格的MySql架构: primary_data

    CREATE TABLE `primary_data` (
      `Chapter` varchar(50) NOT NULL,
      `No` varchar(50) NOT NULL,
      `Additional1` varchar(50) DEFAULT NULL,
      `Additional2` varchar(50) DEFAULT NULL,
      `Additional8` varchar(50) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    表格的MySql架构: suffix_values

    CREATE TABLE `suffix_values` (
      `Id` bigint(20) NOT NULL AUTO_INCREMENT,
      `Chapter` varchar(50) DEFAULT '',
      `allowed_suffix` char(5) NOT NULL DEFAULT '',
      `IsEnabled` tinyint(1) DEFAULT '0',
      PRIMARY KEY (`Id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
    

    表格的MySql架构: allowednumbers (值1到999)

    CREATE TABLE `allowednumbers` (
      `Number` int(11) NOT NULL,
      PRIMARY KEY (`Number`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    视图的MySql架构: vnumbers (需要在MS Sql中重新创建)

    SELECT  `primary_data`.`Chapter` AS `Owner`,
        `primary_data`.`Additional1` AS `Chapter`,
        `primary_data`.`Additional8` AS `ThisYear`,
        CAST(`primary_data`.`No` AS UNSIGNED) AS `scrubbed_number`
    FROM    `primary_data`
    WHERE   (
            (`primary_data`.`Additional8` <> '')
            AND `primary_data`.`Additional1` IN (   
            SELECT `suffix_values`.`Chapter`
            FROM    `suffix_values`
            WHERE ((`suffix_values`.`isenabled` = 1)
            AND (`suffix_values`.`allowed_suffix` NOT IN ('e' , 'ee'))
            )
        )
    )    
    ORDER BY `primary_data`.`Additional1` , CAST(`primary_data`.`No` AS UNSIGNED)
    

    结果查询语句的MySql (我在此帖子的where子句中放置了常量值,还需要在MS Sql中重新创建)

    Select Tens,
    CASE col0
     WHEN 0 Then '~'
     ELSE col0
     END '0',
    CASE col1
     WHEN 0 Then '~'
     ELSE col1
     END '1',
    CASE col2
     WHEN 0 Then '~'
     ELSE col2
     END '2',
    CASE col3
     WHEN 0 Then '~'
     ELSE col3
     END '3',
    CASE col4
     WHEN 0 Then '~'
     ELSE col4
     END '4',
    CASE col5
     WHEN 0 Then '~'
     ELSE col5
     END '5',  
    CASE col6
     WHEN 0 Then '~'
     ELSE col6
     END '6',
    CASE col7
     WHEN 0 Then '~'
     ELSE col7
     END '7',
    CASE col8
     WHEN 0 Then '~'
     ELSE col8
     END '8',
    CASE col9
     WHEN 0 Then '~'
     ELSE col9
     END '9' 
    From (
        Select Concat('',x.row,'0''s') as Tens,  
        sum(x.Col0) 'col0', 
        sum(x.Col1) 'col1', 
        sum(x.Col2) 'col2', 
        sum(x.Col3) 'col3', 
        sum(x.Col4) 'col4', 
        sum(x.Col5) 'col5', 
        sum(x.Col6) 'col6', 
        sum(x.Col7) 'col7', 
        sum(x.Col8) 'col8', 
        sum(x.Col9) 'col9' 
    From (
    Select Left(cast(a.Number as char(3)),Length(cast(a.Number as char(3)))-1) 'Row',  
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '0' then a.number
     Else 0
    END 'Col0',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '1' then a.number
     Else 0
    END 'Col1',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '2' then a.number 
     Else 0
    END 'Col2',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '3' then a.number 
     Else 0
    END 'Col3',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '4' then a.number 
     Else 0
    END 'Col4',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '5' then a.number 
     Else 0
    END 'Col5',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '6' then a.number 
     Else 0
    END 'Col6',
    CASE  Right(cast(a.Number as char(3)),1)
    WHEN '7' then a.number 
     Else 0
    END 'Col7',
    CASE  Right(cast(a.Number as char(3)),1)  
    WHEN '8' then a.number 
     Else 0
    END 'Col8',
    CASE  Right(cast(a.Number as char(3)),1)  
    WHEN '9' then a.number 
     Else 0
    END 'Col9'
    From  allowednumbers as a
    Where (a.Number Not Between 1 and 25) and a.Number NOT IN (
    Select scrubbed_number 
    From vnumbers as b 
    Where (b.Owner='South' and b.Chapter='South') and b.ThisYear= '2014')
    Order by Cast(Left(cast(a.Number as char(3)), Length(cast(a.Number as char(3)))-1) as unsigned) 
    ) as x
    Group by x.Row
    Order by Cast(x.Row as unsigned)
    ) as z
    

1 个答案:

答案 0 :(得分:0)

我之前的回答出现了问题......我发现有些数据行不符合我的期望......所以我用一个函数解决了这个问题:

CREATE FUNCTION dbo.getnumberonly
(
    @p1 nvarchar(50)
)
RETURNS int
AS
BEGIN   
Return
    case (patindex('%[a-z]%',@p1)) 
        when 0 then @p1 
        else 
            case (patindex('%[0-9]%',@p1)) 
                when 1 then  -- Numbers first
                    substring(@p1, patindex('%[0-9]%',@p1), len(@p1) - patindex('%[0-9]%',reverse(@p1)) + patindex('%[0-9]%',@p1)) 
                else 
                 dbo.getnumberonly(substring(@p1, patindex('%[0-9]%',@p1), len(@p1) - patindex('%[0-9]%',@p1)))
            end
    end
END