2012-03-29 231 views
1

遇到特定存储过程的麻烦。我认为我有它大部分是正确的... 我基本上想要能够搜索一个月和一年,并有任何产品的行在该时间表内出售。SQL - 将MONTH提取从数字转换为完整的月份名称

CREATE PROCEDURE sp_products 
    @productname CHAR(20), 
    @month  CHAR(9), 
    @year   CHAR(4) 


AS 
SELECT p.ProductName, 
     p.UnitPrice, 
     p.UnitsInStock, 
     s.Name 

FROM  Orders o 
INNER JOIN OrderDetails od 
ON   o.OrderID = od.OrderID 
INNER JOIN Products p 
ON   od.ProductID = p.ProductID 
INNER JOIN Suppliers s 
ON   p.SupplierID = s.SupplierID 

WHERE p.ProductName = @productname 
AND  MONTH(o.OrderDate) = @month 
AND  YEAR(o.OrderDate) = @year 

给我一个“将转换varchar值'December'转换为数据类型为int的转换失败。错误。

下面是它需要与之合作的查询:

EXEC sp_products '%tofu%', 'December', 1992 

我想我知道我需要做的,只是不知道该怎么做...
帮助!

+0

您是否将int转换为varchar? MONTH在你的表格中的数据类型是什么? – Milee 2012-03-29 05:14:54

回答

0

一个月字符串转换为每月的1-12表示,使用内置的功能DATENAME - 重建你的约会对象喜欢的东西,1922年12月01日,然后使用该输入DATENAME

+0

好的,谢谢,但是让我们说我不能改变输入......那么我该怎么做? – Serenity 2012-03-29 05:31:59

+0

您必须对输入进行一些后处理。用日= 1(它是不相关的)和输入的月/年来重建日期时间。 – hkf 2012-03-29 06:30:37

1

MONTH( )返回一个int。

而是一个月(o.OrderDate),尝试DATENAME(男,o.OrderDate)

编辑:

另外请注意,您的输入不会给你结果你正在使用通配符,而不使用LIKE运营商。

更新这一行你的程序:

WHERE p.ProductName LIKE @productname 
+0

好吧,没有错误,但没有回报任何东西......我认为你是在做些什么!谢谢! – Serenity 2012-03-29 05:32:05

+0

您在产品名称中使用通配符,但您使用“=”进行比较。要得到结果并输入“%tofu%”,请将p.ProductName =/@ ProductName更改为p.ProductName LIKE/@ ProductName – jlnorsworthy 2012-03-29 05:49:30

+0

大声笑,似乎mutilpe @符号不被stackoverflow赞赏。上面的例子 – jlnorsworthy 2012-03-29 05:50:21

0

如回答jlnorsworthy

“相反MONTH(o.OrderDate),尽量DATENAME(男,o.OrderDate)”

这将起作用

无法查看您输入的内容

EXEC sp_products '%豆腐%',“去年12月,1992年

您使用=操作

WHERE p.ProductName = @productname 

变化对照它=喜欢它会奏效。

1

以下两个条件,可能使您的查询非sargable,因为在每种情况下你申请到列的功能正在对过滤:

AND  MONTH(o.OrderDate) = @month 
AND  YEAR(o.OrderDate) = @year 

我会改变他们是这样的:

SELECT  … 
      … 
      … 

FROM  Orders o 

/* this join actually replaces those two filters */ 
INNER JOIN (SELECT CAST('1-' + @month + CAST([email protected] AS varchar(5))) AS Month) d 
ON   o.OrderDate >= d.Month AND o.OrderDate < DATEADD(MONTH, 1, d.Month) 

INNER JOIN … /* the rest of your joins */ 

WHERE  p.ProductName = @productname /* only one condition here now */ 

也就是说,参数@year@month被格式化为一个可转换为日期时间值的字符串,代表相应月份的第一个值,然后您使用t他的逻辑:

order date >= the first of the given month 
and 
order date < the first of the next month after the given 

当然而且,正如你已经被告知,在查询中@productname过滤器也许应该像你想要用面膜来搜索使用LIKE比较,而不是=,因为它似乎以及具体的名称。因此,WHERE子句将如下所示:

WHERE  p.ProductName LIKE @productname 
相关问题