ショッピング Web サイトで 2 つ以上の製品の比較データを保存したいと考えています。
次のリンクを見つけましたが、試してみるとパフォーマンスの問題がありました
SQL Group By / Count: 複数の列で同じ値をカウントしますか?
データをどのように保存できますか? 比較履歴データのテーブル スキーマと、最も比較された製品を表示するにはどうすればよいですか? クエリは何になりますか?
ショッピング Web サイトで 2 つ以上の製品の比較データを保存したいと考えています。
次のリンクを見つけましたが、試してみるとパフォーマンスの問題がありました
SQL Group By / Count: 複数の列で同じ値をカウントしますか?
データをどのように保存できますか? 比較履歴データのテーブル スキーマと、最も比較された製品を表示するにはどうすればよいですか? クエリは何になりますか?
質問はかなり広く、少しあいまいです。私の答えには、あなたがすでに行った考慮事項が含まれている可能性があります。
比較ロジックを実行するには、次の 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 つしかない場合でも問題なく動作します。必要に応じて編集または変更できます。