CREATE TYPE [dbo].[Param] AS TABLE ( [FlagVal] NVARCHAR(100) )
GO
DECLARE @Param [dbo].[Param];
INSERT INTO @Param ( [FlagVal] )
VALUES ( 'Yes' )
, ( 'NO' )
, ( 'Maybe_JKL' )
, ( 'Maybe_XYZ' )
--, ( 'Maybe_PQR' )
;
DECLARE @Sql NVARCHAR(MAX);
SET @Sql = N'
DECLARE @DataT TABLE ( [ID] INT IDENTITY(1,1), [Flag] INT, [FValY] NVARCHAR(45), [FValN] NVARCHAR(45), [FValMB] NVARCHAR(45) );
INSERT INTO @DataT ( [Flag], [FValY], [FValN], [FValMB] )
VALUES ( 10, ''XYZ'', NULL, NULL )
, ( 10, ''ABC'', NULL, NULL )
, ( 10, ''XYZ'', NULL, NULL )
, ( 100, NULL, ''MNO'', NULL )
, ( 100, NULL, ''STU'', NULL )
, ( 1000, NULL, NULL, ''Maybe_JKL'' )
, ( 1000, NULL, NULL, ''Maybe_XYZ'' )
, ( 1000, NULL, NULL, ''Maybe_PQR'' )
, ( NULL, NULL, NULL, NULL )
, ( NULL, NULL, NULL, NULL );
SELECT [ID]
, [Flag]
, [FValY]
, [FValN]
, [FValMB]
FROM @DataT DT
WHERE [ID] < 1000'
IF EXISTS (SELECT TOP (1) 1 FROM @Param) -- Code within this clause needs improvement
BEGIN
SET @Sql = CONCAT(@Sql,N' AND (');
IF EXISTS (SELECT TOP (1) 1 FROM @Param WHERE [FlagVal] = 'Yes')
BEGIN
SET @Sql = CONCAT(@Sql,N' [Flag] = 10');
END
ELSE
BEGIN
SET @Sql = CONCAT(@Sql,N' [Flag] != 10');
END
IF EXISTS (SELECT TOP (1) 1 FROM @Param WHERE [FlagVal] = 'NO')
BEGIN
SET @Sql = CONCAT(@Sql,N' OR [Flag] = 100');
END
ELSE
BEGIN
SET @Sql = CONCAT(@Sql,N' AND [Flag] != 100');
END
IF EXISTS (SELECT TOP (1) 1 FROM @Param WHERE [FlagVal] NOT IN ('Yes','No'))
BEGIN
SET @Sql = CONCAT(@Sql,N' OR ([Flag] = 1000
AND EXISTS (SELECT TOP (1) 1
FROM @Param P
WHERE DT.[FValMB] = P.[FlagVal]))');
END
ELSE
BEGIN
SET @Sql = CONCAT(@Sql,N' AND ([Flag] != 1000
AND NOT EXISTS (SELECT TOP (1) 1
FROM @Param P
WHERE DT.[FValMB] = P.[FlagVal]))');
END
SET @Sql = CONCAT(@Sql,N' )');
END
PRINT @Sql
EXEC sp_executesql
@Sql,
N'@Param [dbo].[Param] READONLY',
@Param = @Param
DROP TYPE [dbo].[Param]
GO
Goal:
High level: filter @DataT data by what's selected in @Param. If @Param is empty, don't filter the data.
Low level:
@Param: this is a filter param that, when populated, will have either "Yes", "No", or a specific "Maybe_xxx" values. This is used to filter the data available in @DataT table.
@DataT: this is the actual data table. It has an Id column (Identity), a Flag column (Yes (10), No (100), and Maybe (1000)), and one column for each flag type ([FValY] is populated for "Yes/10" flag, [FValN] is populated for "No/100" flag, and [FValMB] is populated for "Maybe/1000" flag)
How does the @Param filter work? This filter can be empty or populated with either Yes and/or No and/or specific [FValMB] column's value(s). It can have any combinations of Yes/No/[FValMB]-value(s).
If
@Paramis only populated with "Yes", only the first three records should be returned.If
@Paramis only populated with "No", only the 4th and 5th records should be returned.If
@Paramis only populated with "Maybe" ([FValMB]values), then only the records for "Maybe" flags should be returned where that@Param value(s) = [FValMB].If "Yes" and "No" are populated, then only the first five records should be returned.
If "Yes" and "Maybe" are populated, then only the first three and whatever matches from 6th to 8th records should returned ... and so on
If
@Paramis empty, no filter should apply for this.
My attempt:
I'm having trouble with the arithmetic part where I need to check for the one/more combinations and such. I need help with improving the code within the most outer IF statement.