【问题标题】:SQL Server Stored Procedure Multiple CondtionsSQL Server 存储过程多个条件
【发布时间】:2015-05-19 04:27:59
【问题描述】:

我在 C# 中有这个 LINQ,我必须将其转换为 SQL 查询。而且我不确定如何根据条件进行多重过滤:

var geofenceReport = companyContext.GeofenceSimpleReports.Where(x => x.EnterTime != null && x.ExitTime != null && x.MinutesInGeofence != null).AsQueryable();

if (model.GeofenceId != -1)
{
    geofenceReport = geofenceReport.Where(x => x.iGeofenceId == model.GeofenceId).AsQueryable();
}

if (model.AssetId != -1)
{
    geofenceReport = geofenceReport.Where(x => x.iAssetId == model.AssetId).AsQueryable();
}

if (model.CategoryId != -1)
{
    geofenceReport = geofenceReport.Where(x => x.iCategoryId == model.CategoryId).AsQueryable();
}

if (model.SiteId != -1)
{
    geofenceReport = geofenceReport.Where(x => x.iSiteId == model.SiteId).AsQueryable();
}

geofenceReport = geofenceReport
                   .Where(x => x.EnterTime >= model.StartDateTime && 
                          x.EnterTime <= model.EndDateTime) 
                   .AsQueryable();

这就是我在 SQL 中提出的:

我为AssetId创建了一个新类型:

USE myDatabase
GO

CREATE TYPE idTable AS TABLE (id INT)

然后在 SQL 中:

USE myDatabase
GO

CREATE PROCEDURE [dbo].[xPT_GetGeofenceSummaryReport]
    @iAssetIds idTable,
    @iGeofenceId INT,
    @iCategoryId INT,
    @iSiteId INT,
    @iAssetId INT
AS

IF @iAssetId != -1
    SELECT * FROM GeofenceSimpleReport WHERE iAssetId in (@iAssetIds)

IF @iGeofenceId != -1
    SELECT * FROM GeofenceSimpleReport where iGeofenceId = @iGeofenceId

IF @iCategoryId != -1
    SELECT * FROM GeofenceSimpleReport where iCategoryId = @iCategoryId

IF @iSiteId != -1
    SELECT * FROM GeofenceSimpleReport where iSiteId = @iSiteId

这个GeofenceSimpleReport 是一个数据库视图。

但这不起作用,因为它在逻辑上是错误的。这将从GeofenceSimpleReport 中选择4 个单独的选项。

我需要从GeofenceSimpleReport 读取一个并应用所有过滤器。

而且我不想将这些数据临时读入内存中的 TABLE/LIST,因为有很多数据。

有没有办法像我在 LINQ 中那样动态地编写这个查询?

【问题讨论】:

  • 为什么不直接使用 LINQ?你看起来不错,只要你的查询字段应该缩小结果集(例如,'color = red' AND 'clothingType = sock')。
  • 因为这是一份带回大量数据的报告。并导致 SQL 超时.... :-(
  • 根据数据量,您可以尝试对不同的字段进行索引。你要带回多少行?
  • ' GeofenceSimpleReport ' 是一个数据库视图,它正在连接 5 个表。然后我必须在视图上应用过滤器。
  • 您仍然可以索引视图和基础表。

标签: sql sql-server linq tsql


【解决方案1】:

您是在程序上考虑这一点,并通过一系列 if 语句,而不是将您的视图视为一组可以一次过滤的数据。

您可以根据与 EntryTime、ExitTime 等相关的原始条件进行过滤,然后对于您提供可过滤值(不是 -1)的每个参数,然后确保 Id 与表中的记录匹配。您为该值提供 -1 的任何内容都会自动使 AND 声明为真。

我总是通过传入可空参数来做这种事情——如果它们不是NULL,那么我会过滤它们——否则它们只会评估为true并通过。

USE myDatabase
GO

CREATE PROCEDURE [dbo].[xPT_GetGeofenceSummaryReport]
    @iAssetIds idTable,
    @iGeofenceId INT,
    @iCategoryId INT,
    @iSiteId INT,
    @iAssetId INT
AS
SELECT * 
   FROM GeofenceSimpleReport
   WHERE EnterTime IS NOT NULL 
   AND ExitTime IS NOT NULL
   AND MinutesInGeofence IS NOT NULL
   AND (@iAssetId = -1 OR iAssetId IN (@iAssetIds))
   AND (@iGeofenceId = -1 OR iGeofenceId = @iGeofenceId)
   AND (@iCategoryId = -1 OR iCategoryId = @ICategoryId)
   AND (@iSiteId = -1 OR iSiteId = @iSiteId)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    相关资源
    最近更新 更多