Sql – 存储过程带有多个 if 条件

huangapple go评论65阅读模式
英文:

Sql - Stored Procedure with multiple if condition

问题

以下是您要翻译的内容:

这是我创建的记录表

    CREATE TABLE [dbo].[Graph] (
	[RequestID] [int] NOT NULL,
	[ModuleName] [nvarchar](50) NULL,
	[Info] [float] NULL,
	[HR] [float] NULL,
	[SR] [float] NULL,
	[ISIM] [float] NULL,
	[RequestCreatedDate] [datetime2](7) NULL,
	[RequestModifiedDate] [datetime2](7) NULL,

|RequestID|ModuleName|Info|HR|SR|ISIM|RequestCreatedDate | 
|---------|----------|----|--|--|----|-------------------|  
| 1000    | ECE      | 7  |7 |4 | 8 |	2023-01-09 00:00:00.0000000 | 2023-01-10 00:00:00.0000000  
| 1001    | EEE |	9 |	5 |	2 |	1 |	2023-01-15 00:00:00.0000000 | 2023-01-15 00:00:00.0000000  
| 1002    | ECE |	5 | 3 |	3 |	4 |	2023-01-29 00:00:00.0000000 | 2023-01-29 00:00:00.0000000   
| 1003 | EEE |	6 |	6 |	2 |	2 |	2023-03-08 00:00:00.0000000 | 2023-03-08 00:00:00.0000000  
| 1004 | CSE |	8 |	3 |	3 |	1 |	2023-04-04 00:00:00.0000000 | 2023-04-04 00:00:00.0000000  
| 1005 | CSE |	2 |	2 |	2 |	2 |	2023-04-17 00:00:00.0000000 | 2023-04-17 00:00:00.0000000         
| 1006 | CSE |	4 |	4 |	4 |	4 |	2023-05-09 00:00:00.0000000 | 2023-05-09 00:00:00.0000000

我尝试创建一个带有多个“if”条件的存储过程

1. 如果ModuleName = null,则必须计算从开始到结束的列“Info”,“HR”,“SR”和“ISIM”的平均值。

2. 如果ModuleName = CSE,则必须计算模块名为CSE的列“Info”,“HR”,“SR”和“ISIM”的平均值。

3. 如果start_date = null,end_date = null,意味着必须显示从请求创建日期的开始到当前日期的所有请求。

4. 如果start_date =某个日期(例如02-02-2023),end_date = null,意味着必须显示从特定start_date到当前日期的请求。

5. 如果start_date =某个日期(例如02-02-2023),end_date =某个日期(例如30-04-2023),意味着必须仅显示在特定start_date和end_date之间创建的请求。

6. 如果start_date = null,end_date =某个日期(30-04-2023),则必须显示从开始到end_date创建的请求。

我尝试编写此存储过程,但确切不知道如何编写这些条件的查询,是否可以有人帮助我编写包括这些条件的存储过程查询?我在这方面是初学者。谢谢。

    Alter proc avg_calc (
    @module_name  nvarchar(max) = Null,@start_date datetime2 = null,
    @end_date datetime2 = null)
    As
    Begin
    Declare @sql nvarchar(max), @where nvarchar(max) = '', @where1 datetime2 = ''
        set @sql = 'Select AVG(Info) as Info,
		AVG([HR]) as [HR],
		AVG([SR]) as [SR],
		AVG([ISIM]) as [ISIM]
    FROM Graph'
    If @module_name is not null
    set @where = @where + 'AND ModuleName = @_module_name'
    If @start_date is not null 
    set @where1 = @where1 + 'AND RequestCreatedDate = @_start_date '
    If @end_date is not null 
    set @where1 = @where1 + 'AND RequestModifiedDate = @_end_date '

    If LEN(@where) > 0
    Set @sql = @sql + 'WHERE' + RIGHT(@where, LEN(@where)-5)
    If LEN(@where1) > 0
    Set @sql = @sql + 'WHERE' +RIGHT(@where1, LEN(@where1)-10)
   
    Exec sp_executesql @sql, N'@_module_name nvarchar(100)', 
    @_module_name = @module_name

    Exec sp_executesql @sql, N'@_start_date datetime2, @_end_date datetime2', 
    @_start_date = @start_date, @_end_date = @end_date

    End 


    EXEC avg_calc @module_name='CSE'
 
    EXEC avg_calc @start_date = '02-02-2023', @end_date = '30-02-2023'

希望这可以帮助您。如果您有其他问题,请随时提出。

英文:

This is the table I have Created with the records

CREATE TABLE [dbo].[Graph](
[RequestID] [int] NOT NULL,[ModuleName] [nvarchar](50) NULL,[Info] [float] NULL,[HR] [float] NULL,[SR] [float] NULL, [ISIM] [float] NULL,[RequestCreatedDate] [datetime2](7) NULL,[RequestModifiedDate] [datetime2](7) NULL,
RequestID ModuleName Info HR SR ISIM RequestCreatedDate
1000 ECE 7 7 4 8 2023-01-09 00:00:00.0000000
1001 EEE 9 5 2 1 2023-01-15 00:00:00.0000000
1002 ECE 5 3 3 4 2023-01-29 00:00:00.0000000
1003 EEE 6 6 2 2 2023-03-08 00:00:00.0000000
1004 CSE 8 3 3 1 2023-04-04 00:00:00.0000000
1005 CSE 2 2 2 2 2023-04-17 00:00:00.0000000
1006 CSE 4 4 4 4 2023-05-09 00:00:00.0000000

I have tried to create a Stored procedure with multiple 'if' conditions like

1.ModuleName = null, it has to calculate the average of columns 'Info',' HR',' SR', and 'ISIM' from start to end.

2.ModuleName = CSE, it has to calculate the average of columns 'Info',' HR',' SR', and 'ISIM' of module name with CSE only.

3.if start_date = null, end_date = null means it has to show all the requests from the start of the requestcreateddate to the till date.

4.if start_date = some date(eg02-02-2023), end_date = null means it has to show the requests from that particular start_date to the till date.

5.if start_date = some date (eg 02-02-2023), end_date = some date (eg 30-04-2023) means it has to show only the request created in between that particular start_date and end_date.

6.if start_date = null and end_date = some date (30-04-2023) means it has to show the request created from the start to the end_date.

I just tried writing this stored procedure, but I exactly don't know how to write a query for these conditions, can someone help me in writing a stored procedure query including these conditions? I'm a beginner in this. Thanks.

Alter proc avg_calc (
@module_name  nvarchar(max) = Null,@start_date datetime2 = null,
@end_date datetime2 = null)
As
Begin
Declare @sql nvarchar(max), @where nvarchar(max) = '' , @where1 datetime2 = ''
    set @sql = 'Select AVG(Info) as Info,
	AVG([HR]) as [HR],
	AVG([SR]) as [SR],
	AVG([ISIM]) as [ISIM]
FROM Graph'
If @module_name is not null
set @where = @where + 'AND ModuleName = @_module_name'
If @start_date is not null 
set @where1 = @where1 + 'AND RequestCreatedDate = @_start_date '
If @end_date is not null 
set @where1 = @where1 + 'AND RequestModifiedDate = @_end_date '

If LEN(@where) > 0
Set @sql = @sql + 'WHERE' + RIGHT(@where, LEN(@where)-5)
If LEN(@where1) > 0
Set @sql = @sql + 'WHERE' +RIGHT(@where1, LEN(@where1)-10)

Exec sp_executesql @sql, N'@_module_name nvarchar(100)', 
@_module_name = @module_name

Exec sp_executesql @sql, N'@_start_date datetime2, @_end_date datetime2', 
@_start_date = @start_date, @_end_date = @end_date

End 


EXEC avg_calc @module_name='CSE'

EXEC avg_calc @start_date = 02-02-2023, @end_date = 30-02-2023

答案1

得分: 3

我认为你不需要在这个任务中使用动态SQL。你可以简单地使用类似这样的方法:

CREATE PROCEDURE avg_calc (
    @module_name nvarchar(max) = Null,
    @start_date datetime2 = null,
    @end_date datetime2 = null)
AS
SELECT AVG(Info) as Info,
    AVG([HR]) as [HR],
    AVG([SR]) as [SR],
    AVG([ISIM]) as [ISIM]
FROM Graph
WHERE (ModuleName = @module_name OR @module_name IS NULL)
AND (RequestCreatedDate >= @start_date OR @start_date IS NULL)
AND (RequestCreatedDate <= @end_date OR @end_date IS NULL)
OPTION (RECOMPILE)

我使用了OPTION (RECOMPILE)来尝试在每次执行时使用最佳的执行计划,假设这个存储过程不经常执行,但表的大小相当大(因此编译时间与执行时间相比可以忽略不计),并且ModuleNameRequestCreatedDate上有一些索引。如果这个假设不正确,你应该删除OPTION (RECOMPILE)

有关更多信息,请阅读https://www.sommarskog.se/dyn-search.html。

英文:

I don't think you need to use dynamic SQL for this task. You could simply use something like this:

CREATE PROCEDURE avg_calc (
@module_name  nvarchar(max) = Null,
@start_date datetime2 = null,
@end_date datetime2 = null)
AS
SELECT AVG(Info) as Info,
	AVG([HR]) as [HR],
	AVG([SR]) as [SR],
	AVG([ISIM]) as [ISIM]
FROM Graph
WHERE (ModuleName = @module_name OR @module_name IS NULL)
AND (RequestCreatedDate &gt;= @start_date OR @start_date IS NULL)
AND (RequestCreatedDate &lt;= @end_date OR @end_date IS NULL)
OPTION (RECOMPILE)

I have used OPTION (RECOMPILE) to try to use an optimal execution plan for each execution, assuming that this procedure is not executed very often, but the table size is quite big (so the compilation time would be negligible compared to the execution time) and there are some indexes on ModuleName and RequestCreatedDate. If this assumption is incorrect, you should remove OPTION (RECOMPILE).

For more information, please read https://www.sommarskog.se/dyn-search.html.

答案2

得分: 2

您的sp_executesql出现了两次,而@where1是一个datetime2,这没有意义。

此外,不清楚您要筛选哪个日期字段。您有两个日期字段,并且对一个日期字段进行开始筛选,对另一个日期字段进行结束筛选。

请注意数据类型:@module_name应该是nvarchar(max)还是nvarchar(100)

此外,请注意日期使用了&gt;=&lt;。例如,如果您想要获取整个2023-05-10的结果,您应该传入2023-05-10 00:00:002024-05-11 00:00:00

英文:

You have sp_executesql twice, plus @where1 is a datetime2 which makes no sense.

Furthermore, it's unclear which date field you want to filter. You have two and are filtering against one for the start and the other for the end.

Pay attention to data types: is @module_name supposed to be nvarchar(max) or nvarchar(100)?

CREATE OR ALTER PROC avg_calc
  @module_name nvarchar(100) = NULL,
  @start_date datetime2 = NULL,
  @end_date datetime2 = NULL
AS

DECLARE @sql nvarchar(max);
SET @sql = &#39;
SELECT
    AVG(Info) AS Info,
    AVG(HR) AS HR,
    AVG(SR) AS SR,
    AVG(ISIM) AS ISIM
FROM Graph
WHERE 1=1&#39;;

IF @module_name IS NOT NULL
    SET @sql += &#39;
  AND ModuleName = @module_name&#39;;

IF @start_date IS NOT NULL
    SET @sql += &#39;
  AND RequestCreatedDate &gt;= @start_date&#39;;

IF @end_date IS NOT NULL
    SET @sql += &#39;
  AND RequestCreatedDate &lt; @end_date&#39;;

PRINT @sql;  -- your friend

EXEC sp_executesql @sql,
  N&#39;@module_name nvarchar(100),
    @start_date datetime2,
    @end_date datetime2&#39;, 
  @module_name = @module_name
  @start_date = @start_date,
  @end_date = @end_date;

Also note the use of &gt;= and &lt; for the dates. For example, if you want results for the whole of 2023-05-10 you should pass in 2023-05-10 00:00:00 and 2024-05-11 00:00:00.

huangapple
  • 本文由 发表于 2023年5月11日 01:50:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76221314.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定