给梦一个奔跑的方向!
PDF Print E-mail
User Rating: / 0
PoorBest 
Written by xlingfairy
Tuesday, 21 April 2009 22:05
本地测试数据库中 产品库里有 41万多条数据,有440个分类,分类是树状的。
这两天为了从指定分类里取出每组十条数据来,搞的头大。
给的分类可以是父分类,也可以是叶子分类,这样就要求先查出每个分类下所有子(孙)分类。

数据库里有一个现成的函数,但是每次只能取一个分类的子孙分类,如果用它的话,可能需要多条SQL才能达到目的。

原来做MySQL的时候,相同的问题,我用的是递归,但是SQLServer 里有个 TABLE 类型,用起来更方便。

子查询IN 非常方便,但是这里却不能用,因为程序向存储过程传参数 不能用这样的形式:

355,189,181,7

上面这些数字,个数是可变的,要向存储过程传这些东东,只能用字符串来做: "355,189,181,7"。但是用字符串传到有存储过程后,子查询IN 里就没有办法使用这个参数了。如:
ID IN ('355,189,181,7')
在MSSQL里直接报错,因为 ID 是 int 类型,在MYSQL里不报错,但是你只能得到和355相关的数据。

MySQL里,有个 FIND_IN_SET 可以解决这个问题,比如说:
FIND_IN_SET(ID,'355,189,181,7')。
但是MSSQL里我还不知道要用什么函数来做。不过我变通了一下,把 '355,189,181,7' 变成 ',355,189,181,7,' ,一前一后多加了两个逗号,然后把 ID 用 CAST 转成 VARCHAR型,在用 CHARINDEX函数 来判断是不是在那个串字符串里:

CHARINDEX(',' + CAST(CategoryID AS VARCHAR) + ',' , @CATIDS) > 0

经测试,很有效。

把上面所说的问题解决了,却遇到了另外一个难题,如何按分类,每组取出十条记录出来,MySQL 里,我做过,如:http://home.blueidea.com/space.php?uid=164225&do=blog&id=9938

但是 MSSQL 里却不能这样做,因为:
向变量赋值的 SELECT 语句不能与数据检索操作结合使用。

这真是让人头痛,费了大力气写的存储过程却用不上,还得一个分类一个分类的执行SQL,数据太多,执行的很慢,只有在页面加个:<%@ OutputCache Duration="7200" VaryByParam="none" %> 了。

下面是TABLE数据类型的使用示例,值得一看,MySQL 里没这种类型,只有用递归来解决,如:
http://home.blueidea.com/space.php?uid=164225&do=blog&id=9507



--CREATE FUNCTION GetSubCategory(@CATIDS VARCHAR(1000))
ALTER FUNCTION GetSubCategory(@CATIDS VARCHAR(1000))
RETURNS @RESULT TABLE (ID INT ,PARENTID INT, LEVEL INT) AS
BEGIN
DECLARE @LEVEL INT;
SET @LEVEL = 1;
SET @CATIDS = ',' + REPLACE(@CATIDS,' ','') + ',';
--SET @CATIDS = ',355,189,181,7,'; 

INSERT INTO @RESULT
SELECT
CategoryID,ParentID,@LEVEL
FROM
CSK_Store_Category
WHERE
--CHARINDEX(',' + CAST(ParentID AS VARCHAR) + ',' , @CATIDS) > 0
  CHARINDEX(',' + CAST(CategoryID AS VARCHAR) + ',' , @CATIDS) > 0
 ORDER BY PARENTID;


WHILE @LEVEL < 1000 BEGIN

INSERT INTO @RESULT
SELECT
C.CategoryID,C.ParentID,@LEVEL + 1
FROM
CSK_Store_Category C JOIN
@RESULT R ON C.ParentID = R.ID AND @LEVEL = R.LEVEL;

IF @@ROWCOUNT = 0 BREAK;

SET @LEVEL = @LEVEL + 1;
END;

RETURN;
END;






SELECT
P.ProductID,
P.ProductName,
P.DefaultImage,
PCM.CategoryID,
------------------------------
--不加这段,速度可以提高 6 秒!
CASE C.Level
WHEN 1 THEN ID
ELSE dbo.GetCategoryRootID(C.ID)
END AS GROUPID
------------------------------
FROM
CSK_Store_Product P LEFT JOIN
CSK_Store_Product_Category_MAP PCM ON P.ProductID = PCM.ProductID INNER JOIN
[dbo].GetSubCategory('355,181,189,7') AS C ON PCM.CategoryID = C.ID
WHERE
P.IsMerge = 1
AND P.DefaultImage is not null
AND LTRIM(P.DefaultImage) <> ''
ORDER BY
GroupID,P.CreatedOn DESC

上面这个SELECT 依然很慢,慢的不可接受。
Last Updated ( Tuesday, 21 April 2009 22:16 )
 

Add comment


Security code
Refresh

Popular Contents

Recommend

Related Articles

Site Info

Members : 1
Content : 130
Web Links : 7
Content View Hits : 99670

Links