2015-05-20 66 views
3

我正在写一个产品搜索模块,使用分面搜索。为了简化事情,有两个实体:产品和价格信息。由于产品可以由多个网络商店销售,因此一个产品可以具有更多的价格信息记录。DISTINCT内数SQL Server

产品

- product_guid 
- product_category 
- product_brand 

priceInformation

- priceInformation_guid 
- priceInformation_price 
- priceInformation_product_guid 

我列出所有产品中的特定类别,用户可以按价格范围进行筛选。价格范围用复选框列出,在每个价格范围后面,您可以看到符合搜索条件的产品数量。不显示匹配的价格范围。对于每个价格范围,我都会进行查询以确定匹配数(方面数)。

select count(distinct(product.product_guid)) as count 
from product 
    INNER JOIN priceInformation ON product.product_guid = 
    priceInformation.priceInformation_product_guid 
WHERE category= 'beer' 
    AND product.priceInformation_price > 20 
    AND product.priceInformation_price <= 30 

一切工作正常,但...因为范围的数量在不断增长(这只是一个简单的例子)我执行数百个查询的每一个搜索。这是一个很大的性能杀手。我试图在一个查询中获得所有方面的数据,但由于产品和priceInformation之间存在1:n关系,结果是匹配的价格数量,而不是产品数量。

select (Count(Case WHEN product.priceInformation_price > 20 AND 
         product.priceInformation_price <= 30 THEN 1 
        ELSE NULL END)) as Range2030, 
     (Count(Case WHEN product.priceInformation_price > 30 AND 
         product.priceInformation_price <= 40 THEN 1 
        ELSE NULL END)) as Range3040 
from product 
    INNER JOIN priceInformation ON product.product_guid = 
    priceInformation.priceInformation_product_guid 
WHERE category= 'beer' 

底线是,我错过了DISTINCT这里。我把我的头发拉出来好几天。谁能帮忙?

回答

1

使用派生表来获得不同的价格范围,做一个GROUP BY来计数不同。例如:

select count(distinct(dt.product_guid)), dt.pricerange as count 
from 
(
select product.*, case when price < 20 then 'price < 20' 
         when price between 20 and 30 then 'price 20 - 30' 
         else 'price > 30' end as pricerange 
from product 
    INNER JOIN priceInformation ON product.product_guid = 
    priceInformation.priceInformation_product_guid 
WHERE category= 'beer' 
) dt 
group by dt.pricerange 

或者我现在在这里回答其他的东西......?

+0

这就像一个魅力!在压力测试(250'范围)中,我测得总查询时间缩短了98%。谢谢!!! –

+0

不客气!很高兴听到它的工作! – jarlh

0

我想你应该创建一个价格范围,例如表:

create table PriceRanges(minPrice money,maxPrice money); 
insert PriceRanges values (0,9),(10,19),(20,29),(100,149) ; 

然后使用该表的查询是:

SELECT minPrice,maxPrice,COUNT(DISTINCT p.product_guid) 
    as ProductCount 
FROM PriceRanges pr 
LEFT JOIN priceInformation pi ON pi.priceInformation_price 
      BETWEEN pr.minPrice AND pr.maxPrice 
LEFT JOIN product p ON pi.priceInformation_product_guid= p.product_guid 
WHERE p.product_category = 'beer' 
GROUP BY minPrice,maxPrice 
ORDER BY minPrice 

Sqlfiddle demo

或使用JOIN代替如果您不需要空的价格范围,则可以选择LEFT JOIN。