Sql 如何对存储过程中的同一列使用两个参数

Sql 如何对存储过程中的同一列使用两个参数,sql,tsql,stored-procedures,Sql,Tsql,Stored Procedures,我试图找到一个关于堆栈溢出的类似问题,但没有成功 这是我的存储过程代码: USE [DATABASENAME] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[SPNAME] @IN_dtmin datetime, @IN_dtmax datetime = null, @IN_key varchar(500), @IN_set varchar(80), @IN_l

我试图找到一个关于堆栈溢出的类似问题,但没有成功

这是我的存储过程代码:

USE [DATABASENAME]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SPNAME]
  @IN_dtmin datetime, 
  @IN_dtmax datetime = null, 
  @IN_key varchar(500), 
  @IN_set varchar(80), 
  @IN_locktype varchar(500)
WITH EXEC AS CALLER
AS
BEGIN
      -- SET NOCOUNT ON added to prevent extra result sets from
      -- interfering with SELECT statements.
      SET NOCOUNT ON;

    -- Insert statements for procedure here
SELECT IDLOCK, DT, LOCKTYPE,
       MAX(CASE WHEN PRODUCTATTRIBUTE = 'CodeSet' THEN  VALUE END) AS CodeSet,
       MAX(CASE WHEN PRODUCTATTRIBUTE = 'KeySet' THEN  VALUE END) AS KeySet
FROM LOCKREGISTER LR LEFT JOIN 
     LOCKTYPES T
     ON LR.IDLOCKTYPE = T.IDLOCKTYPE LEFT JOIN 
     PRODUCTATTRIBUTES PA
     ON LR.IDPRODUCT = PA.IDPRODUCT AND 
        PRODUCTATTRIBUTE IN ('CodeSet','KeySet')
WHERE LR.DT BETWEEN IIF(@IN_DTMIN IS NULL,GETDATE(),@IN_DTMIN) AND IIF(@IN_DTMAX IS NULL,GETDATE(),@IN_DTMAX)
  AND (PA.VALUE like ISNULL(@IN_key,'%') OR (PA.VALUE IS NULL AND @IN_key IS NULL)) 
  AND (PA.VALUE like ISNULL(@IN_set,'%') OR (PA.VALUE IS NULL AND @IN_set IS NULL))
  AND (T.LOCKTYPE like ISNULL(@IN_locktype,'%') OR (T.LOCKTYPE IS NULL AND @IN_locktype IS NULL))
GROUP BY IDLOCK, DT, LOCKTYPE;
END
如果不应用任何过滤器,则会出现以下结果:

这是使用
日期过滤器和
设置过滤器执行存储过程的结果:

如上图所示,在代码集列中,结果变为“NULL”

我如何保持这些值​​执行SP时代码集列的名称?(在某些情况下,某些筛选器可能为空)

这是第一行所需结果的示例:


我从您的代码中了解到的是,您只需要一个ISNULL函数。因此,请将SELECT查询升级到-

SELECT IDLOCK, DT, LOCKTYPE,
       ISNULL(MAX(CASE WHEN PRODUCTATTRIBUTE = 'CodeSet' THEN  VALUE END), @IN_set) AS CodeSet,
       ISNULL(MAX(CASE WHEN PRODUCTATTRIBUTE = 'KeySet' THEN  VALUE END), @IN_set) AS KeySet
FROM LOCKREGISTER LR LEFT JOIN 
     LOCKTYPES T
     ON LR.IDLOCKTYPE = T.IDLOCKTYPE LEFT JOIN 
     PRODUCTATTRIBUTES PA
     ON LR.IDPRODUCT = PA.IDPRODUCT AND 
        PRODUCTATTRIBUTE IN ('CodeSet','KeySet')
WHERE LR.DT BETWEEN IIF(@IN_DTMIN IS NULL,GETDATE(),@IN_DTMIN) AND IIF(@IN_DTMAX IS NULL,GETDATE(),@IN_DTMAX)
  AND (PA.VALUE like ISNULL(@IN_key,'%') OR (PA.VALUE IS NULL AND @IN_key IS NULL)) 
  AND (PA.VALUE like ISNULL(@IN_set,'%') OR (PA.VALUE IS NULL AND @IN_set IS NULL))
  AND (T.LOCKTYPE like ISNULL(@IN_locktype,'%') OR (T.LOCKTYPE IS NULL AND @IN_locktype IS NULL))
GROUP BY IDLOCK, DT, LOCKTYPE;

我认为问题在于
PRODUCTATTRIBUTES
是一个实体属性值(Entity Attribute Value,EAV)表,这在查询中很难处理

请注意,在第二次执行包含参数的查询时,为
@in_set
输入的值显示在
KeySet
列中,因为您没有在
WHERE
子句中区分
PRODUCTATTRIBUTE
值(
CodeSet
vs
KeySet

为了简化这样的查询中的逻辑,我通常重复地连接到EAV表,创建只包含每个属性所需的键/值对的子查询。因此,在本例中,我将加入
PRODUCTATTRIBUTES
两次,一次检索感兴趣的
code集
值,然后再次获取
键集
值。我还将把聚合转移到这些子查询,这样可以消除歧义,并减少拉入内存的数据量

当然,这是未经测试的,因为缺少可供测试的表和数据,但对新结构的有根据的猜测可能是这样的

SELECT IDLOCK, DT, LOCKTYPE,
       CS.CodeSet,
       KS.KeySet
FROM LOCKREGISTER LR LEFT JOIN 
     LOCKTYPES T
     ON LR.IDLOCKTYPE = T.IDLOCKTYPE LEFT JOIN 
     ( -- Sub-query to get 'CodeSet' values by IDPRODUCT
      SELECT 
        IDPRODUCT,
        MAX(VALUE) AS CodeSet
      FROM PRODUCTATTRIBUTES
      WHERE PRODUCTATTRIBUTE = 'CodeSet'
      GROUP BY IDPRODUCT
     ) AS CS
     ON LR.IDPRODUCT = CS.IDPRODUCT LEFT JOIN
     (  -- Sub-query to get 'KeySet' values by IDPRODUCT
      SELECT 
        IDPRODUCT,
        MAX(VALUE) AS KeySet
      FROM PRODUCTATTRIBUTES
      WHERE PRODUCTATTRIBUTE = 'KeySet'
      GROUP BY IDPRODUCT
     ) AS KS
     ON LR.IDPRODUCT = KS.IDPRODUCT

WHERE LR.DT BETWEEN IIF(@IN_DTMIN IS NULL,GETDATE(),@IN_DTMIN) AND IIF(@IN_DTMAX IS NULL,GETDATE(),@IN_DTMAX)
  AND (KS.KeySet like ISNULL(@IN_key,'%') OR (KS.KeySet IS NULL AND @IN_key IS NULL)) 
  AND (CS.CodeSet like ISNULL(@IN_set,'%') OR (CS.CodeSet IS NULL AND @IN_set IS NULL))
  AND (T.LOCKTYPE like ISNULL(@IN_locktype,'%') OR (T.LOCKTYPE IS NULL AND @IN_locktype IS NULL));

那很有效!谢谢Eric的时间和解释。