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
vsKeySet
)
为了简化这样的查询中的逻辑,我通常重复地连接到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的时间和解释。