2012-06-10 89 views
1

我正在使用SQL Server 2008,我迫切需要sql查詢或存儲過程來顯示任何類別或子類別中的頂級品牌。例如,如果我通過IdCategory = 2,結果集應顯示電子產品中的頂級品牌,通過對idCategory = 2以及其子類別和子子類別執行產品計數。如果我通過IdCategory = 38,結果應顯示電話&移動設備以及移動電話中的頂級品牌。我希望我能夠明確我的要求。任何類別或子類別中的熱門品牌列表

下面是我的數據庫中的表格。

分類

IdCategory CategoryName    ParentCategoryId 
--------------------------------------------------------- 
1    Appliances    Null 
2    Electronics    Null 
38   Phones & Mobile Devices 2 
39   Cameras & Photography  2 
115   Mobile Phones    38 
121   Digital Cameras   39 

品牌

IdBrand  BrandName 
------------------------ 
1    Nokia 
2    Samsung 
3    Canon 

下表打破了許多人類別和品牌表之間的多對多關係

CategoriesBrands

IdCategoriesBrand IdCategory IdBrand 
----------------------------------------- 
1     2   1 
2     38   1 
3     115   1 
4     2   2 
5     38   2 
6     115   2 

產品

IdProduct  Product Name  IdCategory IdBrand 
--------------------------------------------------------- 
1    AAAA    115   1 
2    BBBB    115   2 
3    CCCC    121   3 
4    DDDD    115   1 
5    EEEE    121   3 

假設有關產品表

  • 產品只能在第三層子子類(E添加。3G手機,數碼Camerass)

這裏是腳本來創建表

CREATE TABLE [dbo].[Categories](
    [IdCategory] [bigint] NOT NULL, 
    [CategoryName] [nvarchar](50) NULL, 
    [ParentCategoryId] [bigint] NULL 
    CONSTRAINT [PK_Categories_IdCategory] PRIMARY KEY CLUSTERED ( [IdCategory] ASC) 
) ON [PRIMARY] 

GO 


CREATE TABLE [dbo].[Brands](
    [IdBrand] [bigint] NOT NULL, 
    [BrandName] [nvarchar](50) NULL 
    CONSTRAINT [PK_Brands_IdBrand] PRIMARY KEY CLUSTERED ( [IdBrand] ASC) 
) ON [PRIMARY] 

GO 

CREATE TABLE [dbo].[CategoriesBrands](
    [IdCategoriesBrand] [bigint] NOT NULL, 
    [IdCategory] [bigint] NULL, 
    [IdBrand] [bigint] NULL, 
    CONSTRAINT [PK_CategoriesBrands] PRIMARY KEY CLUSTERED ( [IdCategoriesBrand] ASC) 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[CategoriesBrands] WITH CHECK ADD CONSTRAINT [FK_CategoriesBrands_Brands] FOREIGN KEY([IdBrand]) 
REFERENCES [dbo].[Brands] ([IdBrand]) 
GO 

ALTER TABLE [dbo].[CategoriesBrands] CHECK CONSTRAINT [FK_CategoriesBrands_Brands] 
GO 

ALTER TABLE [dbo].[CategoriesBrands] WITH CHECK ADD CONSTRAINT [FK_CategoriesBrands_Categories] FOREIGN KEY([IdCategory]) 
REFERENCES [dbo].[Categories] ([IdCategory]) 
GO 

ALTER TABLE [dbo].[CategoriesBrands] CHECK CONSTRAINT [FK_CategoriesBrands_Categories] 
GO 

CREATE TABLE [dbo].[Products](
    [IdProduct] [bigint] NOT NULL, 
    [ProductName] [nvarchar](200) NULL, 
    [IdCategory] [bigint] NULL, 
    [IdBrand] [bigint] NULL 
    CONSTRAINT [PK_Products_IdProduct] PRIMARY KEY CLUSTERED ( [IdProduct] ASC) 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [FK_Products_Brands] FOREIGN KEY([IdBrand]) 
REFERENCES [dbo].[Brands] ([IdBrand]) 
GO 

ALTER TABLE [dbo].[Products] CHECK CONSTRAINT [FK_Products_Brands] 
GO 

ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [FK_Products_Categories] FOREIGN KEY([IdCategory]) 
REFERENCES [dbo].[Categories] ([IdCategory]) 
GO 

ALTER TABLE [dbo].[Products] CHECK CONSTRAINT [FK_Products_Categories] 
GO 

下面是腳本插入表格

INSERT INTO Categories (IdCategory, CategoryName, ParentCategoryId) VALUES(1, 'Appliances', NULL) 
INSERT INTO Categories (IdCategory, CategoryName, ParentCategoryId) VALUES(2, 'Electronics', NULL) 
INSERT INTO Categories (IdCategory, CategoryName, ParentCategoryId) VALUES(38, 'Phones & Mobile Devices', 2) 
INSERT INTO Categories (IdCategory, CategoryName, ParentCategoryId) VALUES(39, 'Cameras & Photography', 2) 
INSERT INTO Categories (IdCategory, CategoryName, ParentCategoryId) VALUES(115, 'Mobile Phones', 38) 
INSERT INTO Categories (IdCategory, CategoryName, ParentCategoryId) VALUES(121, 'Digital Cameras', 39) 


INSERT INTO Brands (IdBrand, BrandName) VALUES(1, 'Nokia') 
INSERT INTO Brands (IdBrand, BrandName) VALUES(2, 'Samsung') 
INSERT INTO Brands (IdBrand, BrandName) VALUES(3, 'Canon') 


INSERT INTO CategoriesBrands (IdCategoriesBrand, IdCategory, IdBrand) VALUES(1, 2, 1) 
INSERT INTO CategoriesBrands (IdCategoriesBrand, IdCategory, IdBrand) VALUES(2, 38, 1) 
INSERT INTO CategoriesBrands (IdCategoriesBrand, IdCategory, IdBrand) VALUES(3, 115, 1) 
INSERT INTO CategoriesBrands (IdCategoriesBrand, IdCategory, IdBrand) VALUES(4, 2, 2) 
INSERT INTO CategoriesBrands (IdCategoriesBrand, IdCategory, IdBrand) VALUES(5, 38, 2) 
INSERT INTO CategoriesBrands (IdCategoriesBrand, IdCategory, IdBrand) VALUES(6, 115, 2) 


INSERT INTO Products (IdProduct, ProductName, IdCategory, IdBrand) VALUES(1, 'AAAA', 115, 1) 
INSERT INTO Products (IdProduct, ProductName, IdCategory, IdBrand) VALUES(2, 'BBBB', 115, 2) 
INSERT INTO Products (IdProduct, ProductName, IdCategory, IdBrand) VALUES(3, 'CCCC', 121, 3) 
INSERT INTO Products (IdProduct, ProductName, IdCategory, IdBrand) VALUES(4, 'DDDD', 115, 1) 
INSERT INTO Products (IdProduct, ProductName, IdCategory, IdBrand) VALUES(5, 'EEEE', 121, 3) 

一些樣本數據到目前爲止,我已經試過這裏面給我的前5個品牌沒有分類

SELECT TOP 5 
    b1.IdBrand, 
    ISNULL(b1.BrandName, '') AS BrandName, 
    count(p.IdProduct) AS 'ProductsCount' 
FROM Brands b1 
LEFT OUTER JOIN Products p 
ON b1.IdBrand = p.IdBrand 
GROUP BY b1.IdBrand, b1.BrandName 
ORDER BY ProductsCount DESC 
+2

它更多的看起來像你的任務/你在這裏委託功課。 – Luftwaffe

+0

一些腳本來創建表和插入也將是有幫助的 - 我只需要一個'產品'和'類' –

+0

不,這不是作業/任務,實際上我創建了一個消費產品評論網站並停留在此查詢上。以下是您提出的完整腳本。 – Waqas

回答

3

這裏是我在解決這一嘗試:

  • 首先獲得所有的類別,從根一個開始(使用遞歸CTE)
  • 計算品牌排名由的categoryId
  • 爲每個類別,顯示前5名品牌

我也做了SQLFiddle在那裏你可以玩的查詢:http://sqlfiddle.com/#!3/8593b/12

這是代碼:

declare @IdCategory bigint 

set @IdCategory = 2 

declare @selectedCategories 
    table (IdCategory bigint primary key) 


-- Use a recursive CTE to determine all 
-- Categories that derive from current 
-- Category 
;with SelectedCategories as (
    select @IdCategory as IdCategory 
    union all 
    select c.IdCategory 
    from Categories c 
    join SelectedCategories sc 
     on sc.IdCategory = c.ParentCategoryId 
) 
-- Save Selected Categories 
-- in a memory table 
insert @selectedCategories (IdCategory) 
select IdCategory from SelectedCategories 

-- use another CTE to select the 
-- Brands in the Selected Categories 
-- and compute their Category rank 
-- using the RANK() 
;with BrandsPerCategory as (
    select 
    c.IdCategory, 
    cc.CategoryName, 
    b.BrandName, 
    rank() over (
     partition by c.IdCategory 
     order by count(p.IdProduct) desc 
    ) as BrandRank 
    from @selectedCategories c 
    join Categories cc 
    on c.IdCategory = cc.IdCategory 
    join CategoriesBrands cb 
    on cb.IdCategory = c.IdCategory 
    join Brands b 
    on cb.IdBrand = b.IdBrand 
    join Products p 
    on p.IdBrand = b.IdBrand 
    group by 
    c.IdCategory, 
    cc.CategoryName, 
    b.BrandName 
) 
select * 
from BrandsPerCategory 
where BrandRank < 5 
order by IdCategory, BrandRank 

編輯:

如果要對所有選擇的類別的頂級品牌(根+子類別),而不是用於每個類別如在上面的例子中,則可以使用下面的查詢(和this SqlFiddle):

declare @IdCategory bigint 

set @IdCategory = 2 

-- Use a recursive CTE to determine all 
-- Categories that derive from current 
-- Category 
;with SelectedCategories as (
    select @IdCategory as IdCategory 
    union all 
    select c.IdCategory 
    from Categories c 
    join SelectedCategories sc 
     on sc.IdCategory = c.ParentCategoryId 
) 
select top 5 
    b.IdBrand, 
    b.BrandName, 
    count(p.IdProduct) AS 'ProductsCount' 
from SelectedCategories c 
join Categories cc 
    on c.IdCategory = cc.IdCategory 
join CategoriesBrands cb 
    on cb.IdCategory = c.IdCategory 
join Brands b 
    on cb.IdBrand = b.IdBrand 
join Products p 
    on p.IdBrand = b.IdBrand 
GROUP BY b.IdBrand, b.BrandName 
ORDER BY ProductsCount DESC 

編輯2:(該不乘以第N解產品具有的相應CategoriesBrands記錄查到號)

SQLFiddle:http://sqlfiddle.com/#!3/26d60/8

代碼:

;with SelectedCategories as (
    select @IdCategory as IdCategory 
    union all 
    select c.IdCategory 
    from Categories c 
    join SelectedCategories sc 
     on sc.IdCategory = c.ParentCategoryId 
) 
select top 5 
    b.IdBrand, 
    b.BrandName, 
    count(p.IdProduct) AS 'ProductsCount' 
from Brands b 
join Products p 
    on p.IdBrand = b.IdBrand 
where b.IdBrand in (
    select cb.IdBrand 
    from SelectedCategories c 
    join CategoriesBrands cb 
    on cb.IdCategory = c.IdCategory 
) 
GROUP BY b.IdBrand, b.BrandName 
ORDER BY ProductsCount DESC 
+0

非常感謝您的解決方案,這些正是我一直在尋找的。你節省了很多我的時間。我只是有一個困惑,你的第二個解決方案顯示諾基亞productcount 6,而產品表中只有2諾基亞產品。這是爲什麼? – Waqas

+0

@Waqas好趕上!這是因爲這兩款產品已經乘以諾基亞在CategoriesBrands上的連接數量。我會想辦法解決這個問題,併發布更新到我的答案。 – GolfWolf

+0

@Waqas完成;請參閱編輯我的答案。 – GolfWolf

相關問題