【问题标题】:Sql query - getting rid of hard-coded valuesSql 查询 - 摆脱硬编码值
【发布时间】:2012-01-11 15:48:34
【问题描述】:

我有以下疑问:

Select Name,
       case when charindex('I',a.S_Data) > 0 then 1 else 0 end as Illustrated,
       case when charindex('FP',a.S_Data) > 0 then 1 else 0 end as FrontPage,
       case when charindex('BP',a.S_Data) > 0 then 1 else 0 end as BackPage,
       case when charindex('ELP',a.S_Data) > 0 then 1 else 0 end as EDLP,
       case when charindex('PR',a.S_Data) > 0 then 1 else 0 end as SpecialPromo
From Table1

我想做的是将这些过滤器值存储在某种查找表或设置表中。

我正在努力解决如何从查找表中提取值以用于此查询。

【问题讨论】:

  • 不确定你会获得多少,因为我假设你仍然想要与结果中的这些值相关联的硬编码列名(IllustratedFrontPage 等)设置。
  • 为这个选择创建一个视图怎么样?
  • 这就是我的想法——即“值得吗?”
  • 您使用的是哪个版本的 SQL?
  • S_Data 字段的典型内容是什么?目前,每个硬编码值都是根据字段中特定(硬编码)字符串的存在来显示的;它是否只包含这些值,还是也可以包含其他数据?

标签: sql


【解决方案1】:

我能想到至少两个选项...

CREATE TABLE constants (
  id               AS INT,
  Illustrated      AS VARCHAR(3),
  FrontPage        AS VARCHAR(3),
  BackPage         AS VARCHAR(3),
  EDLP             AS VARCHAR(3),
  SpecialPromo     AS VARCHAR(3)
)

INSERT INTO constants SELECT 1, 'I', 'FP', 'BP', 'ELP', 'PR'

SELECT
  Name,
  CASE WHEN CHARINDEX(constants.Illustrated, data.S_Data) > 0 THEN 1 ELSE 0 END   AS Illustrated,
  etc, etc
FROM
  data
INNER JOIN
  constants
    ON constants.id = 1

或者……

CREATE TABLE constants (
  constant_set_id  AS INT,
  constant_name    AS VARCHAR(16),
  value            AS AS VARCHAR(3)
)

INSERT INTO constants SELECT 1, 'Illustrated',  'I'
INSERT INTO constants SELECT 1, 'FrontPage',    'FP'
INSERT INTO constants SELECT 1, 'BackPage',     'BP'
INSERT INTO constants SELECT 1, 'EDLP',         'ELP'
INSERT INTO constants SELECT 1, 'SpecialPromo', 'PR'

SELECT
  Name,
  MAX(CASE WHEN constants.constant_name = 'Illustrated' AND CHARINDEX(constants.value, data.S_Data) > 0 THEN 1 ELSE 0 END)   AS Illustrated,
  etc, etc
FROM
  data
INNER JOIN
  constants
    ON constants.constant_set_id = 1
GROUP BY
  data.name

两者都允许您拥有多组不同的常量。一个是可扩展的,无需更改架构,但查询仍需要更改。

这两种方法的主要优点是您可以在其他地方重复使用常量,但将它们存储在集中位置一次。仅当/当常量中的值需要更新时才相关。通过间接重用。

【讨论】:

    【解决方案2】:

    目前,您的表显然违反了First Normal Form,因为单个字段可以为单个记录保存多个值。

    至少有两种方法可以解决这个问题:

    (1) 如果可以存储在此字段中的唯一值是查询中指定的五个值,则将字符字段替换为五个整数字段可能是有意义的,每个字段都是指定条件的标志 - 即:

    ...
    Illustrated int,
    FrontPage int,
    BackPage int,
    EDLP int,
    SpecialPromo int,
    ...
    

    (2) 如果要存储各种不同的条件,那么我建议为条件添加一个查找表,以及一个条件与原始表之间的链接表 - 像这样:

    Conditions
    ----------
    Condition_id
    Description
    
    Link_Table
    ----------
    Table1_id
    Condition_id
    

    【讨论】:

      【解决方案3】:

      首先,Table1 似乎不是第一范式 (NFNF),因为它违反了以下要求:每个元组的每个属性都只有一个值,每个属性的类型都是该属性的声明类型,即S_Data 有多种标量类型。您将遭受更新异常,例如删除设置可能涉及带有文本连接的UPDATE。考虑到 SQL 没有很好地处理此类数据(即非关系数据)的运算符。

      其次,您的输出表不是最理想的,因为它返回的类型与多个列相同,即它看起来更像一个报告。

      考虑 SQL 中的工作单元是行:

      CREATE TABLE Settings
      (
       Setting VARCHAR(15) NOT NULL UNIQUE
      );
      
      INSERT INTO Settings VALUES ('Illustrated'), ('FrontPage'), ('BackPage'),
                                  ('EDLP'), ('SpecialPromo');
      
      CREATE TABLE Table1
      (
       Name VARCHAR(20) NOT NULL, 
       Setting VARCHAR(15) NOT NULL
          REFERENCES Settings (Setting)
          ON DELETE CASCADE
          ON UPDATE CASCADE, 
       UNIQUE (Name, Setting)
      );
      

      【讨论】:

        猜你喜欢
        • 2019-07-05
        • 2017-08-17
        • 2021-11-09
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多