2009-09-29 80 views
0

我正在使用以下查询返回至少有两个条件匹配的所有记录(provided by Quassnoi)。根据匹配标准搜索

SELECT * 
FROM (
     SELECT ContentID 
     FROM (
       SELECT ContentID 
       FROM VWTenantPropertiesResults 
       WHERE ContentStreet = 'Holderness Road' 
       UNION ALL 
       SELECT ContentID 
       FROM VWTenantPropertiesResults 
       WHERE ContentTown = 'Hull' 
       UNION ALL 
       SELECT ContentID 
       FROM VWTenantPropertiesResults 
       WHERE ContentPostCode = 'HU' 
       ) qi 
     GROUP BY 
       ContentID 
     HAVING COUNT(*) >= 2 
     ) q 
JOIN VWTenantPropertiesResults r 
ON  r.ContentID = q.ContentID 
WHERE ContentBedrooms BETWEEN 1 AND 4 
     AND ContentPrice BETWEEN 50 AND 500 
ORDER BY 
     ContentPrice 

的问题是,它似乎工作的街道和镇搜索时(返回与所请求的街道和镇所有匹配的属性),而不是街道和邮编(返回任何结果)搜索时。要搜索街道和邮政编码以便工作(返回结果),我必须删除以下行;

 UNION ALL 
     SELECT id 
     FROM VWTenantPropertiesResults 
     WHERE ContentTown = 'Hull' 

但后来因为我已经删除上述4条线路,以获得街与邮政编码搜索工作显然城市和邮政编码或城市和街道的搜索不工作。

我想知道有人能提供一些帮助吗?

谢谢。

+0

你如何搜索街道和邮政编码? – manji 2009-09-29 16:07:48

+0

这个UNION + HAVING thingie有什么意义?为什么不选择DISTINCT ... WHERE(街= X和镇= Y)或(街= X和邮政编码= Z)或(镇= Y和邮政编码= Z)? – Zed 2009-09-29 16:09:21

+0

什么是您的ContentPostCode字段的类型? – Zed 2009-09-29 16:10:03

回答

0

我不确定你应该在数据库中执行'至少两个条件'的标准,因为你可能永远不知道哪两个已经被填入。也许相反,这可能适用于你 - 这是一个模式我用经常,应该用标准的任意组合应付(我假设这是一个存储过程里面!):

DECLARE PROCEDURE PropertyList 
@StreetName NVARCHAR(50) = NULL, 
@Town NVARCHAR(50) = NULL, 
@Postcode NVARCHAR(10) = NULL 
AS 

SET NOCOUNT ON 

SELECT 
    * 
FROM 
    VWTenantPropertiesResults 
WHERE 
    ContentBedrooms BETWEEN 1 AND 4 
AND 
    ContentPrice BETWEEN 50 AND 500 
AND 
    (@ContentStreet IS NULL OR ContentStreet = @ContentStreet) 
AND 
    (@ContentTown IS NULL OR ContentTown = @ContentTown) 
AND 
    (@ContentPostcode IS NULL OR ContentTown = @ContentTown) 
ORDER BY 
    ContentPrice 

要从ASP页面中调用这个你会想一些代码是这样的(这可能需要一点调试,我的ASP的VBScript是相当生锈!):

Dim cnn 'As ADODB.Connection 
Dim cmd 'As ADODB.Command 
Dim prmStreet 'As ADODB.Parameter 
Dim prmTown 'As ADODB.Parameter 
Dim prmPostcode 'As ADODB.Parameter 
Dim rstProperty 'As ADODB.RecordSet 
Dim i 'As Integer 

Set cnn = Server.CreateObject("ADODB.Connection") 

cnn.ConnectionString = MyConnectionString 

Set cmd = Server.CreateObject("ADODB.Command") 

Set cmd.ActiveConnection = cnn 

'Set the CommandText property to the name of the stored proc we want to call 
cmd.CommandText = "PropertyList" 
cmd.CommandType = 4 'or adCmdStoredProc if you're using ADOVBS.inc 

If Request.Form("StreetTextBox") = "" Then 
    'No street entered so don't pass it to the stored proc 
Else 
    'A street has been entered so create a parameter... 
    Set prmStreet = cmd.CreateParameter("@StreetName", 203, 1, 50, Request.Form("StreetTextBox")) 

    ' and add it to the Parameters collection of the Command object 
    cmd.Parameters.Add(prmStreet) 
End If 

If Request.Form("TownTextBox") = "" Then 
    'No town entered so don't pass it to the stored proc 
Else 
    'A town has been entered so create a parameter... 
    Set prmTown = cmd.CreateParameter("@Town", 203, 1, 50, Request.Form("TownTextBox")) 

    ' and add it to the Parameters collection of the Command object 
    cmd.Parameters.Add(prmTown) 
End If 

If Request.Form("PostcodeTextBox") = "" Then 
    'No postcode entered so don't pass it to the stored proc 
Else 
    'A postcode has been entered so create a parameter... 
    Set prmPostcode = cmd.CreateParameter("@Postcode", 203, 1, 10, Request.Form("PostcodeTextBox")) 

    ' and add it to the Parameters collection of the Command object 
    cmd.Parameters.Add(prmPostcode) 
End If 

cnn.Open 

'This is the line that'll actually call the stored procedure 
Set rstProperty = cmd.Execute() 

cnn.Close 

If rstProperty.BOF And rstProperty.EOF Then 
    'If BOF And EOF are true then this is an empty recordset - we got no records back 
    Response.Write "No records returned" 
Else 
    'We have records so write them out into a table 
    Response.Write "<table><tr>" 
    For i = 0 To rstProperty.Fields.Count - 1 
     Response.Write "<td>" 
     Response.Write rstProperty.Fields(i).Name 
     Response.Write "</td>" 
     Response.Write "<td>&nbsp;</td>" 
    Next 

    Response.Write "</tr>" 

    Do While rstProperty.Eof = False 
     Response.Write "<tr>" 
     For i = 0 To rstProperty.Fields.Count - 1 
      Response.Write "<td>" 
      Response.Write rstProperty.Fields(i).Value 
      Response.Write "</td>" 
     Next 
     Response.Write "<td>" 
     Response.Write "<a href='ViewDetails.asp?id='" & rstProperty.Fields("PropertyId").Value & "'>View Details for this property</a>" 
     Response.Write "</td>" 
     Response.Write "</tr>" 
     rstProperty.MoveNext 
    Loop 

    Response.Write "</table>" 
End If 

应该工作的任何参数组合,无论你输入没有,其中的一些或全部!

+0

感谢菲尔。我会试试你的解决方案。我是新来的ASP,因为我在我的新工作中继承了旧版网站。在你的解决方案中,程序PropertyList是否也包含一些SQL查询? 我一直在阅读参数化查询,但还没有使用存储过程。 谢谢。 – doubleplusgood 2009-09-29 20:14:07

+0

存储过程是查询!我可以添加一些VBScript代码来演示调用存储过程,如果这对您有用吗? – PhilPursglove 2009-09-30 09:07:52

+0

嘿菲尔。如果不是太麻烦,那会很好吗? – doubleplusgood 2009-09-30 10:03:09

0

查询方法看起来不错。

你是不是指什么意思?它会抛出一个错误,或返回没有结果或意外的结果?

您是否期望使用完整的邮政编码匹配?我看到你的例子使用HU,不知道那是什么。它看起来不像加拿大邮政编码,你在寻找哪个地区?

你能告诉我们你的数据集吗?

+0

这不是加拿大邮政编码,而是英国邮政编码! – PhilPursglove 2009-09-29 16:10:11

+0

我想知道哪个赫尔被提及! – dnagirl 2009-09-29 16:13:07

+0

这确实是赫尔在英国。我相信加拿大的赫尔更令人兴奋。 ;)我实际上稍微改变了这个查询,以便它在输入邮编之前或之后使用LIKE来匹配任何东西。 – doubleplusgood 2009-09-29 19:38:59

0

如果你是正确的,你说的这个查询:

SELECT ContentID 
FROM VWTenantPropertiesResults 
WHERE ContentStreet = 'Holderness Road' 
UNION ALL 
SELECT ContentID 
FROM VWTenantPropertiesResults 
WHERE ContentTown = 'Hull' 
UNION ALL 
SELECT ContentID 
FROM VWTenantPropertiesResults 
WHERE ContentPostCode = 'HU' 

回报率不到2行的一些内容识别,而此查询:

SELECT ContentID 
FROM VWTenantPropertiesResults 
WHERE ContentStreet = 'Holderness Road' 
UNION ALL 
SELECT ContentID 
FROM VWTenantPropertiesResults 
WHERE ContentPostCode = 'HU' 

回报2个或更多相同内容识别。

这似乎在逻辑上是不可能的,除非你的DBMS有一个主要的错误!对于某些展示该问题的ContentID,上述查询返回什么内容?

0

你可能想这样的:

SELECT * 
FROM (
     SELECT ContentID 
     FROM (
       SELECT ContentID 
       FROM VWTenantPropertiesResults 
       WHERE ContentStreet LIKE '%Holderness Road%' -- Take off the leading % if you can 
       UNION ALL 
       SELECT ContentID 
       FROM VWTenantPropertiesResults 
       WHERE ContentTown LIKE '%Hull%' -- Take off the leading % if you can 
       UNION ALL 
       SELECT ContentID 
       FROM VWTenantPropertiesResults 
       WHERE ContentPostCode LIKE '%HU%' -- Take off the leading % if you can 
       ) qi 
     GROUP BY 
       ContentID 
     HAVING COUNT(*) >= 2 
     ) q 
JOIN VWTenantPropertiesResults r 
ON  r.ContentID = q.ContentID 
WHERE ContentBedrooms BETWEEN 1 AND 4 
     AND ContentPrice BETWEEN 50 AND 500 
ORDER BY 
     ContentPrice 

因为在英国没有邮政编码是= 'HU'这将是形式'HU_ ___'所以你需要通配符。

通常我们限制搜索匹配从字符串的开头(帮助搜索索引),但有时用户需要任意搜索。