2

SQL Server 2008を使用していますが、任意のカテゴリまたはサブカテゴリのトップブランドを表示するには、SQLクエリまたはストアドプロシージャが緊急に必要です。たとえば、IdCategory = 2を渡すと、結果セットには、idCategory = 2とそのサブカテゴリおよびサブサブカテゴリで製品カウントを実行することにより、Electronicsのトップブランドが表示されます。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

次の表は、カテゴリとブランドの表の間の多対多の関係を壊します

カテゴリブランド

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

製品表についての仮定

  • 製品は、第3レベルのサブサブカテゴリ(携帯電話、デジタルカメラなど)にのみ追加できます。

テーブルを作成するためのスクリプトは次のとおりです

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
4

1 に答える 1

3

これを解決するための私の試みは次のとおりです。

  • 最初に、ルートから始まるすべてのカテゴリを取得します (再帰 CTE を使用)
  • カテゴリ ID によるブランド ランキングの計算
  • カテゴリごとに上位 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 

編集:

上記の例のように各カテゴリではなく、選択したすべてのカテゴリ (ルート + サブカテゴリ) の上位ブランドが必要な場合は、次のクエリ (およびこの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: (製品の数に対応する 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
于 2012-06-10T13:30:38.057 に答える