【问题标题】:Optional Parameters in mysql select querymysql select查询中的可选参数
【发布时间】:2016-02-15 08:47:02
【问题描述】:

我正在尝试在我的项目中实现可选搜索,该项目有五个可选输入值(CompanyID、PackageID、SubjectID、Fromdate 和 Todate)

我把mysql查询写成

select l.RefNo, l.LetterDate, l.CompanyID, l.Subject,
   c.CompanyID, 
   c.CompanyCode,
   p.PackageName, p.PackageID
   from tblletter l,
   tblcompany c,
   tblpackage p
        where 
        (companyID is null or l.CompanyID = companyID ) and
                     (packageID is null or l.PackageID = packageID) and
                     (subjectID is null or l.LetterID = subjectID);

但我无法得到结果,我需要一种语法将日期值发送为 null,我已尝试为

DateTime? fromdate=....

这个语法正确吗? 谢谢。

将我的代码更新为

select l.RefNo, l.LetterDate, l.CompanyID, l.Subject,
Case LetterType
    When 1 then 'PSK'
    When 2 then c.CompanyCode
End As FromCompany,  
Case LetterType
    When 1 then c.CompanyCode
    When 2 then 'PSK'
End As ToCompany,


 c.CompanyCode,
   p.PackageID
   from tblletter l,
   tblcompany c ,
   tblpackage p  
    where l.CompanyID = c.CompanyID and l.PackageID = p.PackageID and

    l.CompanyID Like 
        case 

            when l.CompanyID = c.CompanyID and companyID > 0 then ('%' + LTRIM(companyID) + '%')
            else '%%'
        end
and l.PackageID Like
          case 

            when l.PackageID = p.PackageID and packageID > 0 then ('%' + LTRIM(packageID) + '%')
            else '%%'
        end  
and l.Subject =
          case 
            when subjectName is not null then  subjectName
            else '%%'
        end;

但仍然得到空表值...

the possible cases are
1). companyID = 30 or packageID = 0 or subjectName = null
2). companyID = 0 or packageID = 11 or subjectName = null
3). companyID = 0 or packageID = 0 or subjectName = 'sand'
4). companyID = 30 and packageID = 11 or subjectName = null
5). companyID = 30 or packageID = 0 and subjectName = 'sand'

如果值为“0”,则必须忽略(或) 等等……像……

【问题讨论】:

  • 不要在查询中添加可选参数,而是尝试在代码中使用条件创建查询,以便最终查询只有所需的参数\
  • 那么,是否需要编写五个单独的存储过程,每个参数一个? @manoj
  • 不不,抱歉,我不知道这是一个存储过程,我以为你是直接从你的 c# 程序触发查询。

标签: c# mysql select optional-parameters


【解决方案1】:

几个建议:

  1. 首先直接运行您的查询(例如,在某些查询编辑器 UI 中)(您 可能已经这样做了,但如果没有,它会有所帮助)
  2. 使用 ANSI 样式连接语法,明确区分三者的连接条件 filter 标准中的表(FROM 子句) WHERE 子句
  3. 您的第一个示例,您在其中测试参数 对于 NULL 并具有 OR 条件,可能更简单,因为引擎 可以立即确定 WHERE 子句的该部分为 TRUE,而不是使用使用 '%%' 的虚拟 LIKE 运算符实际测试行值
  4. 首先使用连接的表运行查询(在编辑器中),但 注释掉整个 WHERE 子句并确保您看到数据。 然后,开始逐步取消注释WHERE 子句, 包括参数值(或代替它们的文字),确保 您会在每个步骤中看到您期望的结果。这将有助于缩小 减少您的故障排除过程。

这是一个展示这些想法的示例查询:

SELECT 
    l.RefNo, l.LetterDate, l.CompanyID, l.Subject,
    Case LetterType
        When 1 then 'PSK'
        When 2 then c.CompanyCode
    End As FromCompany,  
    Case LetterType
        When 1 then c.CompanyCode
        When 2 then 'PSK'
    End As ToCompany,
    c.CompanyCode,
    p.PackageID
FROM tblletter l
INNER JOIN tblcompany c ON l.CompanyID = c.CompanyID   --make sure whether this should be INNER or LEFT OUTER join
INNER JOIN tblpackage p ON l.PackageID = p.PackageID   --make sure whether this should be INNER or LEFT OUTER join
WHERE 1 = 1  --useful if commenting and uncommenting additional parts of WHERE clause
AND (companyID is null OR l.CompanyID = companyID) -- can do the LIKE version instead, but may be slower... test both
AND (packageID is null OR p.PackageID = packageID) -- can do the LIKE version instead, but may be slower... test both
AND (subjectName is null OR l.Subject = subjectName) -- can do the LIKE version instead, but may be slower... test both
;

【讨论】:

  • 感谢您的回复...这里是代码 AND (35 is null OR l.CompanyID = 35) -- 可以改为 LIKE 版本,但可能会更慢...测试 AND (0 is null OR p.PackageID = 0) - 可以使用 LIKE 版本,但可能会更慢...同时测试 AND (null is null OR l.Subject = null) 类似仅包含 companyID 的值.. 但仍然得到空结果..
  • @htiru - 就像我在上面提到的 #4 一样,首先尝试在没有 WHERE 子句的情况下运行查询,这样您就可以验证表连接是否按照您期望的方式工作。如果没有取回数据,则FROM 子句有问题。如果您确实获得了数据,则可以开始逐个添加过滤器(您的 WHERE 子句),并在每个步骤中进行测试以查看导致数据被过滤掉的原因。
  • 在没有 where 子句的情况下可以正常工作,并且连接完成得很完美..@SlimsGhost
  • @htiru - 所以加入工作正常,这很好。现在,如果您将 WHERE 子句的各个部分(一个一个)添加回来,您应该能够看到为什么要返回的数据被过滤掉了。这应该只是一个排除过程,然后找出问题过滤器为什么没有按照您的意愿行事。
【解决方案2】:

首先,您的参数与列同名肯定会引起一些混乱。我会用某种前缀重命名以区分它们,例如“parmCompanyID”、“parmPackageID”等。

接下来,由于您总是以字母开头,并且有条件地连接到 company 和 package,因此我默认在 ID 列上分别对 company 和 package 表进行 JOIN,这将是它们的自然连接。

现在,根据您的标准。要仅根据您实际提供的数据获得结果,该条件是什么。如果您不输入公司 ID,那么您就不会在意并获得所有这些 ID。

如果您确实为公司设定了价值,那么您只需要那些合格的。因此,JOIN 始终基于 ID,但您可以在哪里添加 EXTRA 条件。如果您提供的是 ID 字符串,那么如果字符串的长度为 0(无),则始终返回 TRUE,是的,包括公司。如果长度 > 0(提供的东西),则仅当该 ID 在列表中时才返回 true。

您的其他标准的类似申请。类似的东西

select 
      l.RefNo, 
      l.LetterDate, 
      l.CompanyID, 
      l.Subject,
      Case LetterType 
           When 1 then 'PSK'
           When 2 then c.CompanyCode End As FromCompany,
      Case LetterType
           When 1 then c.CompanyCode
           When 2 then 'PSK' End As ToCompany,
      c.CompanyCode,
      p.PackageID
   from 
      tblletter l,
         JOIN tblcompany c
            ON l.CompanyID = c.CompanyID
         JOIN tblpackage p 
            ON l.PackageID = p.PackageID
   where 
      CASE WHEN LENGTH( LTRIM( parmCompanyID )) = 0
           THEN 1
           ELSE l.CompanyID LIKE '%' + LTRIM(parmCompanyID) + '%' end

      AND
      CASE WHEN LENGTH( LTRIM( parmPackageID )) = 0
           THEN 1
           ELSE l.PackageID LIKE '%' + LTRIM(parmPackageID) + '%' end

      AND
      CASE WHEN LENGTH( LTRIM( parmSubject )) = 0
           THEN 1
           ELSE l.Subject LIKE '%' + LTRIM(parmSubject) + '%' end

反馈

可能是由于 LTRIM() 而不是 FULL TRIM()。如果您的参数有前导空格,则您的通配符匹配将类似于 '%[space][space]something%' 并且可能无法按预期找到。但是查询的上下文应该可以工作,除非字母表中的条目并不总是与给定的公司和/或包相关联,这会使其失败而不是使用 LEFT-JOIN。

另外,如果您提供的值是公司或包裹的 SINGLE ID,那么您无论如何都不应该使用 LIKE...您可能需要更改为...

   where 
      CASE WHEN parmCompanyID = 0
           THEN 1
           ELSE l.CompanyID = parmCompanyID end

      AND
      CASE WHEN parmPackageID = 0
           THEN 1
           ELSE l.PackageID = parmPackageID end

      AND
      CASE WHEN LENGTH( LTRIM( parmSubject )) = 0
           THEN 1
           ELSE l.Subject LIKE '%' + LTRIM(parmSubject) + '%' end

【讨论】:

  • 感谢您的回复@DRapp ...但是 '%' 这在 mysql 中不起作用.. 我测试了这个查询但仍然得到空结果..
  • @htiru,抱歉延迟回复。请参阅修改后的答案。
  • 我很遗憾地说仍然不能使用单个输入值而不是所有输入值 ` where CASE WHEN = 0 THEN 1 ELSE l.CompanyID = 35 end AND CASE WHEN 11 = 0 THEN 1 ELSE l.PackageID = 11 end AND CASE WHEN ENGTH( LTRIM( 4 )) = 0 THEN 1 ELSE l.Subject LIKE LTRIM('sand') end`
  • @htiru,你能编辑你现有的问题,走到它的最后,用一些你试图模拟处理的值的实际样本来编辑......单个,多个,字符串值吗?什么...欣赏它。
猜你喜欢
  • 2013-08-02
  • 2015-09-14
  • 1970-01-01
  • 2023-02-16
  • 2020-09-08
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 2021-02-02
相关资源
最近更新 更多