none
撈取資料的方式,哪個做法比較好? RRS feed

  • 問題

  • 各位大大,小弟有個需求如下,想請教3個做法比較好?
    還是有更建議的方式,感謝大家。

    Table 商品主表,如下: 
    CREATE TABLE [dbo].[Products]
    (
    [ID] [int] IDENTITY(1,1) NOT NULL, --序號
            [Type] [int] NOT NULL,             --商品類型
            [Price] [int] NOT NULL,            --商品價格
            [AskCount] [int] NOT NULL,         --詢問數
            [FavoriteCount] [int] NOT NULL     --收藏數
    )

    有個需求,要在使用者瀏覽商品時,旁邊要顯示5個跟龍蝦相關的熱門商品。

    熱門商品規格: 條件: 目前商品價格 +-10%、相同類型
                  排序: 詢問數 > 收藏數
                  P.S. 但不足5個時,再用波士頓龍蝦(Type = 2)、小龍蝦(Type = 3)...等商品,補滿5個

    例如: User正在看一般龍蝦的商品,商品類型 Type = 1,商品價格 Price = 1500。

    [做法1,程式步驟如下]:
    1.先第1段SQL語法:

    SELECT TOP 5 * 
    FROM [dbo].[Products]
    WHERE [Type] = 1 --類型: 一般龍蝦
    AND [Price] >= 1350 -- 1500 * 0.9
    AND [Price] <= 1650 -- 1500 * 1.1 
    ORDER BY [AskCount] DESC, 
             [FavoriteCount] DESC

    2.C# 判斷 if count < 5,再撈第2段SQL語法:
    SELECT TOP 5 * 
    FROM [dbo].[Products]
    WHERE ([Type] = 2 OR [Type] = 3) --類型: 波士頓龍蝦、小龍蝦
    AND [Price] >= 1350 -- 1500 * 0.9
    AND [Price] <= 1650 -- 1500 * 1.1 
    ORDER BY [AskCount] DESC, 
             [FavoriteCount] DESC

    3.C# 再負責計算補滿5筆,最後輸出

    ====================================

    [做法2,程式步驟如下]:
    1.直接寫個 Stored procedure來處理,撈取一般龍蝦,不足5筆就再撈,
      波士頓龍蝦、小龍蝦,計算補滿5筆

    =================================================================

    [做法3,程式步驟如下]:
    1.直接全撈
    SELECT TOP 5 * 
    FROM [dbo].[Products]
    WHERE ([Type] = 1 OR [Type] = 2 OR [Type] = 3) --類型: 一般龍蝦、波士頓龍蝦、小龍蝦
    AND [Price] >= 1350 -- 1500 * 0.9
    AND [Price] <= 1650 -- 1500 * 1.1 
    ORDER BY [AskCount] DESC, 
             [FavoriteCount] DESC

    2.C# 用LINQ 做處理,
         先抓出一般龍蝦,不足5筆,
         再抓,波士頓龍蝦、小龍蝦,最後計算補滿5筆

    private IEnumerable<Products> GetHotProducts(List<Products> dbResult)
    {
    // 先抓出一般龍蝦 
    var firstResult = dbResult.Where(s => s.Type == 1)
      .OrderByDescending(o => o.AskCount)
      .OrderByDescending(o => o.FavoriteCount)
      .Take(5)
      .Select(p => p.ID);

    // 一般龍蝦的筆數 
    var count = firstResult.Count();

    // 判斷是否有5筆
    if (count < 5)
    {
    // 再抓 波士頓龍蝦、小龍蝦 
    var secondResult = dbResult.Where(s => s.Type == 2 || s.Type == 3)
       .OrderByDescending(o => o.AskCount)
       .OrderByDescending(o => o.FavoriteCount)
       .Take(5-count)
       .Select(p => p.ID);

    return dbResult.Where(s => firstResult.Contains(s.ID) || 
                               secondResult.Contains(s.ID));
    }
    else
    {
    return dbResult.Where(s => firstResult.Contains(s.ID));
    }
    }

    public class Products 
    {
    public int ID { get; set; }
    public int Type { get; set; }
    public int AskCount { get; set; }
    public int FavoriteCount { get; set; }
    }


    2019年2月27日 上午 10:33

解答

  • 您好

    小喵個人建議,一次在SQL中做完
    可以在取TOP 5時,利用『ROW_NUMBER()』來取得之後要排序的欄位ODR2

    在第一個查詢時,給『1』當作是欄位ODR1
    在第二個查詢時,給『2』當作是欄位ODR1

    將兩個結果UNION ALL 起來

    並將UNION ALL之後的結果,用ODR1, ODR2排序

    像這樣

    SELECT TOP 5 *
    FROM 
    (
    	SELECT TOP 5 
    		1 AS ODR1
    		, ROW_NUMBER() OVER(ORDER BY [AskCount] DESC, [FavoriteCount] DESC) AS ODR2
    		, * 
    	FROM [dbo].[Products]
    	WHERE [Type] = 1 --類型: 一般龍蝦
    		AND [Price] >= 1350 -- 1500 * 0.9
    		AND [Price] <= 1650 -- 1500 * 1.1 
    
    	UNION ALL
    
    	SELECT TOP 5 
    		2 AS ODR1
    		, ROW_NUMBER() OVER(ORDER BY [AskCount] DESC, [FavoriteCount] DESC) AS ODR2
    		, * 
    	FROM [dbo].[Products]
    	WHERE ([Type] = 2 OR [Type] = 3) --類型: 波士頓龍蝦、小龍蝦
    		AND [Price] >= 1350 -- 1500 * 0.9
    		AND [Price] <= 1650 -- 1500 * 1.1 
    ) V1
    ORDER BY ODR1, ODR2
    		 
    		 

    當第一個查詢不足5筆沒關係,自然有ODR1=2的可以補上

    您思考一下

    ^.^a


    topcat(姍舞之間的極度凝聚)
    http://www.dotblogs.com.tw/topcat
    世界上有兩樣東西分享給別人後,不但不會變少,還會變更多:
    一個是快樂,另一個是知識~ 分享...是知識累積的開始...

    • 已標示為解答 taco0508 2019年8月12日 上午 08:37
    2019年7月29日 上午 02:56