使用广告

时间:2017-08-09 17:04:27

标签: sql sql-server

我正在寻找一种基于来自另一个SQL查询的条件在表中转换数据的方法。

我的表格如下;

数据表: Id | EntityId | Value1 | Value2 |价值3 ......价值200

实体: Id |名称

字段: Id | EntityId | DataType | FieldNum

查找 Id | EntityId | FieldId

我的理想输出如下:

  • Data.Id [Id]
  • Field.Id [FieldId]
  • Entity.Id [EntityId]
  • [StringVal]
  • [INTVAL]

“StringVal”和“IntVal”都将根据“Fields”表中的“DataType”列设置,如果设置为“lookup”(在“Data”表中以字符串形式存储),它应该在此选择查询中解析为整数并填充在“IntVal”列中,否则,应将其直接解析为[StringVal]列。

我有以下SQL查询,它按预期工作,但是,如果我有200个数据字段,我必须每个字符串和查找复制CASE和WHEN子句200次,然后就会有复杂性添加一个新类型,如“DateTime”,这将导致进一步的问题。

SELECT
  dt.Id as [Id],
  f.Id as [FieldId],
  f.EntityId as [EntityId],
  CASE
    WHEN f.DataType = 'string' and f.FieldNum = 0 THEN dt.Value0
    WHEN f.DataType = 'string' and f.FieldNum = 1 THEN dt.Value1
    WHEN f.DataType = 'string' and f.FieldNum = 2 THEN dt.Value2
    WHEN f.DataType = 'string' and f.FieldNum = 3 THEN dt.Value3
    WHEN f.DataType = 'string' and f.FieldNum = 4 THEN dt.Value4
    WHEN f.DataType = 'string' and f.FieldNum = 5 THEN dt.Value5
    WHEN f.DataType = 'string' and f.FieldNum = 6 THEN dt.Value6
    WHEN f.DataType = 'string' and f.FieldNum = 7 THEN dt.Value7
    WHEN f.DataType = 'string' and f.FieldNum = 8 THEN dt.Value8
    WHEN f.DataType = 'string' and f.FieldNum = 9 THEN dt.Value9
    ELSE NULL
  END as [StringVal],
  CAST(CASE
    WHEN f.DataType = 'lookup' and f.FieldNum = 0 THEN dt.Value0
    WHEN f.DataType = 'lookup' and f.FieldNum = 1 THEN dt.Value1
    WHEN f.DataType = 'lookup' and f.FieldNum = 2 THEN dt.Value2
    WHEN f.DataType = 'lookup' and f.FieldNum = 3 THEN dt.Value3
    WHEN f.DataType = 'lookup' and f.FieldNum = 4 THEN dt.Value4
    WHEN f.DataType = 'lookup' and f.FieldNum = 5 THEN dt.Value5
    WHEN f.DataType = 'lookup' and f.FieldNum = 6 THEN dt.Value6
    WHEN f.DataType = 'lookup' and f.FieldNum = 7 THEN dt.Value7
    WHEN f.DataType = 'lookup' and f.FieldNum = 8 THEN dt.Value8
    WHEN f.DataType = 'lookup' and f.FieldNum = 9 THEN dt.Value9
    ELSE NULL
  END as INT) as [IntVal]
FROM Lookups as i
  left JOIN Fields f on i.FieldId = f.id and i.EntityId = f.EntityId
  INNER join DataTable dt on i.EntityId = dt.EntityId

有没有更简单的方法来实现这一目标?我需要将它保存在索引视图中,因此不能使用存储过程,函数等。

修改

尝试通过以下评论中所述的功能实现此目的,但是发现了同样的问题。以下是我尝试过的功能解决方案。

SELECT
  dt.Id as [Id],
  f.Id as [FieldId],
  f.EntityId as [EntityId],
  CASE
    WHEN f.DataType = 'string' THEN dbo.u_function_return_string
      (
        f.FieldNum, dt.Value0, dt.Value1,
        dt.Value2, dt.Value3, dt.Value4,
        dt.Value5, dt.Value6, dt.Value7,
        dt.Value8, dt.Value9
      )
    ELSE NULL
  END as [StringVal],
  CAST(CASE
    WHEN f.DataType = 'lookup' THEN dbo.u_function_returns_string
      (
         f.FieldNum, dt.Value0, dt.Value1,
         dt.Value2, dt.Value3, dt.Value4,
         dt.Value5, dt.Value6, dt.Value7,
         dt.Value8, dt.Value9
      )
    ELSE NULL
  END as INT) as [IntVal]
FROM dbo.Lookups as i
  INNER JOIN dbo.Fields f on i.FieldId = f.id and i.EntityId = f.EntityId
  INNER join dbo.DataTable dt on i.EntityId = dt.EntityId

功能:

CREATE FUNCTION u_function_return_string(
  @fieldNum INT,
  @val0 NVARCHAR(255),
  @val1 NVARCHAR(255),
  @val2 NVARCHAR(255),
  @val3 NVARCHAR(255),
  @val4 NVARCHAR(255),
  @val5 NVARCHAR(255),
  @val6 NVARCHAR(255),
  @val7 NVARCHAR(255),
  @val8 NVARCHAR(255),
  @val9 NVARCHAR(255)
)
RETURNS NVARCHAR(255) WITH SCHEMABINDING
AS BEGIN
RETURN
  CASE
    WHEN @fieldNum = 0 THEN @val0
    WHEN @fieldNum = 1 THEN @val1
    WHEN @fieldNum = 2 THEN @val2
    WHEN @fieldNum = 3 THEN @val3
    WHEN @fieldNum = 4 THEN @val4
    WHEN @fieldNum = 5 THEN @val5
    WHEN @fieldNum = 6 THEN @val6
    WHEN @fieldNum = 7 THEN @val7
    WHEN @fieldNum = 8 THEN @val8
    WHEN @fieldNum = 9 THEN @val9
  END
END
GO

有没有办法在函数中嵌入“行”?理想情况下,我想提交2个参数,即字段编号和“dt”结果集。

编辑2:

找到一种方法来使一个函数采用一个类型...有效...但无法弄清楚如何从查询中解析“dt。*”到该类型并传递给函数。

CREATE OR ALTER FUNCTION u_function_return_string(
  @fieldNum INT,
  @data dbo.DataTableType READONLY
)
RETURNS NVARCHAR(255) WITH SCHEMABINDING
AS BEGIN
  DECLARE @tmp NVARCHAR(255)
  DECLARE @value NVARCHAR(255)
  set @tmp = 'Value' + CAST(@fieldNum as NVARCHAR(50))
  SET @value = (SELECT @tmp FROM @data)
  RETURN @value
END
GO

1 个答案:

答案 0 :(得分:0)

您可以使用标量值的schemabinding函数和动态sql,并在select查询中使用一个case函数调用替换多个case语句。

我修改了您的查询以解释该方法。请根据您的要求进行更改。

<?php
$cart  = array(
    '547650d3bfb9bce7ea6d61faf312fa41' => array
    (
        'id' => 1502369193000,
        'productid' => 'Product 1',
        'qty' => 1,
        'type' => 'sales',
        'user_id' => 'admin',
        'rowid' => '547650d3bfb9bce7ea6d61faf312fa41'
    ),
    '7473a2e4d2e4150c7de11d201538e179' => array
    (
        'id' => 1502369241000,
        'productid' => 'SG KENNA',
        'qty' => 1,
        'type' => 'purchase',
        'user_id' => 'admin',
        'rowid' => '7473a2e4d2e4150c7de11d201538e179'
    )
);

$found = false;
foreach ($cart as $key => $data) {
    if ($data['user_id'] == 'admin' && $data['type'] == 'sales') {

        $found = true;

    }
}

if ($found === false) {
  echo 'not found';
} else {
    echo 'found';
}

Output is : Found