【问题标题】:Use variable sql for column name使用变量 sql 作为列名
【发布时间】:2018-11-28 14:39:02
【问题描述】:

在你用大写字母骂我没有搜索之前 - 我有!动态 SQL 好,动态 SQL 不好。学到了很多..

我可以通过在 WHERE 子句中使用逻辑来完成我所追求的目标,但它会增加大量的运行时间。如果我对条件进行硬编码,则查询需要 8 秒,如果我使用 WHERE 逻辑,则需要 1:20。

这是我想做的:

Declare @EmployeeToggle varchar(30)
Declare @Employee_ID varchar(30)
Declare @EmployeeField varchar(100)

set @EmployeeToggle = '1'
set @Employee_ID = '1166'
set @EmployeeField = case when @EmployeeToggle = '1' then 'Field1' else 
'Field2' end;

select * from Table1 where @EmployeeField = @Employee_ID

我认为没有动态 sql 是不可能的。我仍然不知道我是否应该使用它。我认为它会将查询时间缩短到 8 秒,因为它会立即知道在 where 子句中使用哪个字段。

或者,仅在 where 中执行此操作的几种方法:

where (( not @EmployeeToggle = '1') or Field1 = @Employee_ID) and 
(@EmployeeToggle = '1' or Field2 = @Employee_ID)


where (1=(case when @EmployeeToggle = '1' then 1 else 0 end ) or Field1 = 
@Employee_ID)
and (1=(case when @EmployeeToggle = '2' then 1 else 0 end) or Field2 = 
@Employee_ID)

这些效果很好(诚然,我复制并粘贴了这些示例),但以牺牲运行时间为代价。

我的最终想法以及其他人在我的组织中所做的方式是创建两个相同的脚本,除了 where 子句中使用的字段。因此,如果 @EmployeeToggle = '1' 它将运行第一个脚本,如果它是 '2' 它将运行第二个脚本。我还没有尝试过,但我认为运行时间会更接近 8 秒,但会牺牲一些丑陋的代码。

感谢您的帮助。

【问题讨论】:

  • 将 IF 条件与两个单独的语句一起使用,这将是您的最佳解决方案,恕我直言
  • 不确定我是否完全理解您的切换要点。既然你说最后一部分工作正常,似乎不需要切换。一个简单的 @Employee_ID in (field1, field2) 怎么样?
  • 它很可能不需要,但我并不完全跟随你。 @Employee_ID in (field1, field2) 在英文中是什么意思?
  • 到目前为止@DenisRubashkin,这个解决方案是唯一一个运行时间可接受的解决方案。

标签: sql sql-server tsql dynamic-sql


【解决方案1】:

为什么不只使用一个查询?

select t.*
from table1
where @EmployeeToggle = '1' and field_1 = @Employee_ID
union all
select t.*
from table1
where @EmployeeToggle <> '1' and field_2 = @Employee_ID;

通过使用union all,SQL Server 应该为每个子查询使用索引——如果字段上有索引,查询应该很快。

【讨论】:

  • 嗯,也许我没有索引——这个方法花了 1:20。假设我正确地实现了它,这是一个很大的假设。它虽然有效。 “我的”代码是 15 个左右 CTE 的混搭,它们在最后以各种方式连接在一起,然后有一个 select * 用于决赛桌。那是我放你的代码的地方。
  • @user2615663 。 . .您的问题与您提出的问题略有不同。需要动态 SQL 可能是对的,但您也可以使用查询提示获得所需的性能。这需要调查不同查询的执行计划。
  • 是的,我一直在努力简化问题以使其更容易发布(并获得答案),或者深入了解我可能理解或什至不理解的细节。新手的生活。我将研究查询提示。不要认为我有权查看执行计划 :( 谢谢
【解决方案2】:

在 SELECT 中使用 CASE 表达式时,您可以保留静态 SQL,然后对其进行过滤。

SELECT *
FROM (
   SELECT *,
          CASE WHEN @EmployeeToggle = '1' THEN Field1 ELSE Field2 END AS Field1_2
   FROM Table1 
) t
WHERE
   Field1_2 = @Employee_ID

【讨论】:

  • 试一试。效果很好,但仍然需要 1:20。
  • @user2615663 尝试在 Filed1 和 Filed2 列上建立两个索引。
【解决方案3】:

这是您的动态查询:

Declare @EmployeeToggle varchar(30)
Declare @Employee_ID varchar(30)
Declare @EmployeeField varchar(100)

set @EmployeeToggle = '1'
set @Employee_ID = '1166'
set @EmployeeField = case when @EmployeeToggle = '1' then 'Field1' else 
'Field2' end;

DECLARE @SQLString  VARCHAR(MAX)

SET @SQLString='select * 
                from Table1 
                where '+@EmployeeField+' = '+@Employee_ID+''

PRINT(@SQLString) --If you want to check actual query
EXEC(@SQLString)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 2021-06-25
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多