如何通过多字段查询创建动态订单

问题描述 投票:0回答:1

我正在尝试创建一个具有多个 order by 字段的存储过程。按字段和方向的顺序作为参数通过存储过程传递。

CREATE PROCEDURE GetFilteredLogs
    @FromDate       datetime2,
    @ToDate         datetime2,
    @SearchText     nvarchar(100) = NULL,
    @LogTypeIds     Ids READONLY,
    @AreaIds        Ids READONLY,
    @SubTypeIds     Ids READONLY,
    @UnitIds        Ids READONLY,
    @SortField      nvarchar(25) = NULL,
    @SortDirection  nvarchar(5) = NULL
AS
    SELECT *
    FROM LogsView
    WHERE   
        (CreatedDate >= @FromDate AND CreatedDate <= @ToDate) 
        AND ((([Text] LIKE '%' + @SearchText + '%' OR @SearchText IS NULL)
              AND (LogTypeId IN (SELECT Id FROM @LogTypeIds) OR NOT EXISTS (SELECT 1 FROM @LogTypeIds))
              AND (OperationAreaId IN (SELECT Id FROM @AreaIds) OR NOT EXISTS (SELECT 1 FROM @AreaIds))
              AND (Subtype IN (SELECT Id FROM @SubTypeIds) OR NOT EXISTS (SELECT 1 FROM @SubTypeIds))
              AND (Unit IN (SELECT Id FROM @UnitIds) OR NOT EXISTS (SELECT 1 FROM @UnitIds))) OR IsCritical = 1)    
ORDER BY
    CASE @SortField
        WHEN 'LogTypeId' THEN CreatedDate DESC(should be passed as argument), LogTypeId DESC
        ELSE CreatedDate DESC
    END

GO

上述存储过程中的 order by 部分语法不正确。我该怎么做?我上面尝试过的方法是否可行?

sql-server t-sql sql-order-by dynamic-sql sql-server-2022
1个回答
3
投票

这是一个经典的厨房水槽查询

使用动态 SQL 构建一系列条件和排序子句。然后使用

sp_executesql
执行它,传入所有必要的参数。

CREATE OR ALTER PROCEDURE GetFilteredLogs
    @FromDate       datetime2,
    @ToDate         datetime2,
    @SearchText     nvarchar(100) = NULL,
    @LogTypeIds     Ids READONLY,
    @AreaIds        Ids READONLY,
    @SubTypeIds     Ids READONLY,
    @UnitIds        Ids READONLY,
    @SortField      nvarchar(25) = NULL,
    @SortDirection  nvarchar(5) = NULL
AS

DECLARE @sql nvarchar(max) = '
SELECT *
FROM LogsView
WHERE (CreatedDate >= @FromDate AND CreatedDate <= @ToDate)
  AND (
    IsCritical = 1
    OR (1=1';

IF @SearchText IS NOT NULL
    SET @sql += '
      AND [Text] LIKE ''%'' + @SearchText + ''%''';

IF EXISTS (SELECT 1 FROM @LogTypeIds)
    SET @sql += '
      AND LogTypeId IN (SELECT Id FROM @LogTypeIds)';

IF EXISTS (SELECT 1 FROM @AreaIds)
    SET @sql += '
      AND OperationAreaId IN (SELECT Id FROM @AreaIds)';

IF EXISTS (SELECT 1 FROM @SubTypeIds)
    SET @sql += '
      AND Subtype IN (SELECT Id FROM @SubTypeIds)';

IF EXISTS (SELECT 1 FROM @UnitIds)
    SET @sql += '
      AND Unit IN (SELECT Id FROM @UnitIds)';

SET @sql += '
    )
  )
ORDER BY
  CreatedDate' + IIF(@SortDirection = 'DESC', ' DESC', '');

IF @SortField = 'LogTypeId'
    SET @sql += ',
LogTypeId' + IIF(@SortDirection = 'DESC', ' DESC', '');

PRINT @sql;  -- your friend

EXEC sp_executesql @sql,
  N'@FromDate       datetime2,
    @ToDate         datetime2,
    @SearchText     nvarchar(100),
    @LogTypeIds     Ids READONLY,
    @AreaIds        Ids READONLY,
    @SubTypeIds     Ids READONLY,
    @UnitIds        Ids READONLY',

    @FromDate = @FromDate,
    @ToDate = @ToDate,
    @SearchText = @SearchText,
    @LogTypeIds = @LogTypeIds,
    @AreaIds = @AreaIds,
    @SubTypeIds = @SubTypeIds,
    @UnitIds = @UnitIds
;

从您的描述中不清楚,但似乎您总是想要按

CreatedDate
排序,并且可能还按
LogTypeId
排序,具体取决于参数。

© www.soinside.com 2019 - 2024. All rights reserved.