2015-05-20 65 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。