0

ショッピング Web サイトで 2 つ以上の製品の比較データを保存したいと考えています。

次のリンクを見つけましたが、試してみるとパフォーマンスの問題がありました

SQL Group By / Count: 複数の列で同じ値をカウントしますか?

データをどのように保存できますか? 比較履歴データのテーブル スキーマと、最も比較された製品を表示するにはどうすればよいですか? クエリは何になりますか?

4

1 に答える 1

0

質問はかなり広く、少しあいまいです。私の答えには、あなたがすでに行った考慮事項が含まれている可能性があります。

比較ロジックを実行するには、次の 3 つが必要です。製品、その製品の評価、および比較のために製品を論理的にグループ化する何らかの方法。通常、適切なインデックスを使用した粒度が最適です。

作成するテーブル/インデックスの例を次に示します。

Create  Table Product (ProductID Int, ProductName Varchar(256), etc)
Create  Table Groups (GroupID Int, GroupName Varchar(256), etc)
Create  Table ProductGroup (ProductID Int, GroupID Int)
Create  Table RatingType (RatingID Int, RatingName Varchar(64))
Create  Table ProductRatings (ProductID Int, RatingID Int, RatingValue Varchar(32))

Create  Clustered Index ix_Product_pID On Product (ProductID)
Create  Nonclustered Index ix_Product_pID_pName On Product (ProductID, ProductName)
Create  Clustered Index ix_Groups_gID On Groups (GroupID)
Create  Nonclustered Index ix_ProductGroup_gID_pID On ProductGroup (GroupID, ProductID)
Create  Clustered Index ix_RatingType_rID On RatingType (RatingID)
Create  Nonclustered Index ix_ProductRatings_pID_rID On ProductRatings (ProductID, RatingID)

Product、Group、および RatingType にクラスター化インデックスを配置することは、それらの ID 列が ID 列になるため理にかなっています。これらは連続するため、物理的な順序について心配する必要はありません。一方、ProductGroup と ProductRatings は、任意のレコードをいつでも任意の順序で受け取ることができるため、それらにクラスター化インデックスを配置すると、挿入が遅くなり、断片化が速くなります。

リンクされた例のクエリで行われたロジックを実行するには、次のようにします。

Create  Proc GetProductComparisonRatings (@productID Int, @ratingID Int)
As

Declare @columns Nvarchar(Max), 
        @SQL Nvarchar(Max);

;With   DistinctCols As
(
        Select  Distinct p.productName
        From    ProductGroup pg1
        Join    ProductGroup pg2
                On  pg1.groupID = pg2.groupID
        Join    Product p
                On  pg2.productID = p.productID
        Where   pg1.productID = @productID      
)
Select  @columns = Coalesce(@columns + ',','') + '[' + productName + ']'
From    DistinctCols
Order   By  Case
            When    p.productID = @productID Then 0
            Else    1
            End;        -- This will put your product that was the basis of the comparison as the leftmost column

Select  @SQL = ';With   baseRecords As
                (
                        Select  pg2.productID, 
                                pr.ratingValue, 
                                Count(1) As cnt
                        From    ProductGroup pg1
                        Join    ProductGroup pg2
                                On  pg1.groupID = pg2.groupID
                        Join    ProductRatings pr
                                On  pg2.productID = pr.productID
                                And pr.ratingID = ' + @ratingID + '
                        Where   pg1.productID = ' + @productID + '
                        Group   By  pg2.productID, 
                                    pr.ratingValue;
                )
                Select  ratingValue, ' + @columns + '
                From    baseRecords br
                Join    product p
                        On  br.productID = p.productID
                Pivot   (Sum(cnt) For p.productName In (' + @columns + ')) pivot';

Exec    sp_executeSQL @SQL;

これはさらに一歩進んで、評価の比較を特定の ratingType に制限します。いくつかの例は(耐久性、サイズ、全体)です。ratingType が 1 つしかない場合でも問題なく動作します。必要に応じて編集または変更できます。

于 2013-01-08T19:00:15.183 に答える