【问题标题】:Filtering products in web app在 Web 应用程序中过滤产品
【发布时间】:2016-08-29 09:43:02
【问题描述】:

我有一个产品表,可以为产品分配任意数量的过滤器规格 - 即颜色、类型等。分配给产品的过滤器值存储在查找表中。这些表有点复杂,但我可以使用的一个简单示例如下:

Products
-----------------
ProdID | Code | Price
1      | A1   | 2.99
2      | B1   | 10.99
10     | F4   | 20.00


Filters
-----------------
FilterID | Name
1        | Black
2        | Blue
4        | Round
10       | Waterproof


ProductFilterLookup
-------------------
ProdID | FilterID
1      | 1
1      | 4
1      | 10
2      | 1
2      | 10
10     | 1

因此,如果用户选择“黑色”和“防水”产品(FilterID 的 1 和 10),预期结果将是 ProdID 的 1 和 2,因为只有这些产品同时具有这两个过滤器。

可以为产品分配任何过滤器。我想获取所有包含一组选定过滤器的产品(意味着它具有所有过滤器值)。

我可以在 LINQ 或 SQL 中执行此操作,并且需要它尽可能高效(性能方面)。

【问题讨论】:

  • 添加一些示例表数据和预期的结果。
  • 对我来说有 3 种方法:第一种是将原始 SQL 语句发送到 SQL Server,第二种是使用实体框架,第三种是使用类型化的数据集——我告诉你,使您的应用类型安全
  • 但是对于您的 SQL 命令:您必须在查找表上进行 SELECT,其中 FilterID 等于您的值,在 Product 表和 Filter 表上使用子 SELECT 来获取过滤器和产品的名称

标签: c# sql asp.net sql-server linq


【解决方案1】:

为了性能 - 您可以让 linq 可能与 sql 一样快。只需一个 sql 和一个 linq 并比较两者的解释计划。看看它为 linq 生成了什么 sql。

你可以测试:

var neededFilters = new List<string> { "Black", "Waterproof" };

var result1 = (from p in products
               join pf in productFilterLookup on p.ProdID equals pf.ProdID
               join f in filters on pf.FilterID equals f.FilterID
               group f.Name by p into grouping
               where neededFilters.All(filter => grouping.Contains(filter))
               select grouping.Key).ToList();

var result = (from p in products
              join f in (from pf in productFilterLookup
                         join f in filters on pf.FilterID equals f.FilterID
                         select new { pf.ProdID, f.Name })
                         on p.ProdID equals f.ProdID into grouping
              where neededFilters.All(filter => grouping.Any(item => item.Name == filter))
              select p).ToList();

【讨论】:

  • 他问如何在 linq 或 SQL 中做到这一点?
  • 谢谢,试试看。
  • @Simon - Cool :) 很高兴来到这里 :)
【解决方案2】:

@西蒙

为了回答您的问题,以下 SQL 语句将帮助您:

SELECT pfl.id, p.productid, p.code, p.price, f.filterid, f.name 
FROM 
    productfilterlookup pfl
INNER JOIN
    products p ON (pfl.productid = p.productid)
INNER JOIN
    filters f ON (pfl.filterid = f.filterid)
WHERE pfl.filterid = 1 OR pfl.filterid = 10;

这会输出一些像这样的输出:

+----+-----------+------+-------+----------+--------------+
| id | productid | code | price | filterid | name         |
+----+-----------+------+-------+----------+--------------+
|  1 |         1 | A1   |  2.99 |        1 | Black        |
|  3 |         1 | A1   |  2.99 |       10 | Waterproofed |
|  4 |         2 | B1   | 10.99 |        1 | Black        |
|  5 |         2 | B1   | 10.99 |       10 | Waterproofed |
|  6 |        10 | F4   | 20.00 |        1 | Black        |
+----+-----------+------+-------+----------+--------------+

【讨论】:

  • 谢谢,问题是我不知道会选择多少个过滤器。我想我可以在代码中动态生成 SQL。
  • 如果您使用 SQL 进行操作,那么您可以(必须)动态生成您的 SQL 语句 => 使用上面的代码并将 - 生成的循环 - WHERE 部分附加到 SELECT...FROM ...INNER JOIN ...部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
  • 2021-05-14
  • 2021-12-09
  • 1970-01-01
相关资源
最近更新 更多