sql - 多对多选择查询

标签 sql sql-server database join

我正在尝试编写代码以从 SQL Server 数据库中提取产品项目列表并将结果显示在网页上。

该项目的一个需求是在页面右侧显示一个类别列表作为一个复选框列表(默认选中所有类别),用户可以取消选中类别并重新查询数据库以查看产品只属于他们想要的类别。

这里开始变得有点毛茸茸了。

可以使用如下产品类别表将每个产品分配到多个类别...

Product table
[product_id](PK),[product_name],[product_price],[isEnabled],etc...

Category table
[CategoryID](PK),[CategoryName]

ProductCagetory table

[id](PK),[CategoryID](FK),[ProductID](FK)

我需要选择一个产品列表,这些产品与传递到我的存储过程的一组类别 ID 相匹配,其中产品有多个分配的类别。

类别 ID 作为逗号分隔的 varchar 传递给 proc,即 ( 3,5,8,12 )

SQL 将此 varchar 值分解为临时表中的结果集以供处理。

我将如何编写此查询?

最佳答案

一个问题是将选定类别的数组或列表传递到服务器。 Eland Sommarskog 在系列文章中全面介绍了该主题 Arrays and Lists in SQL Server .将列表作为逗号分隔的字符串传递并构建临时表是一种选择。还有其他选择,例如使用 XML 或表值参数(在 SQL Server 2008 中)或使用表 @variable 而不是 #temp 表。我链接的文章中介绍了各自的优缺点。

现在介绍如何检索产品。首先要做的事情是:如果选择了所有 类别,则使用不同的查询来简单地检索所有产品,而根本不考虑类别。这将节省很多性能,并且考虑到所有用户可能首先会看到一个未选择任何类别的页面,节省的费用可能非常可观。

选择类别 后,构建连接产品、类别和所选类别的查询就相当容易了。使其扩展和执行是一个不同的主题,并且完全取决于您的数据模式和所选类别的实际模式。一个天真的方法是这样的:

select ...
from Products p
where p.IsEnabled = 1
and exists (
  select 1  
  from ProductCategories pc
  join #selectedCategories sc on sc.CategoryID = pc.CategoryID
  where pc.ProductID = p.ProductID);

ProductsCategoriestable 必须在 (ProductID, CategoryID) 上有一个索引,在 (CategoryID, ProductID) 上有一个索引(其中一个是聚类,一个是 NC)。顺便说一句,对于每个解决方案都是如此。如果始终选择大多数 类别并且结果包含大多数 产品,则此查询将有效。但是,如果所选类别的列表是限制性的,那么最好避免扫描可能较大的产品表并从所选类别开始:

with distinctProducts as (
select distinct pc.ProductID
from ProductCategories pc
join #selectedCategories sc on pc.CategoryID = sc.CategoryID)
select p.*
from Products p
join distinctProducts dc on p.ProductID = dc.ProductID;

同样,最佳解决方案在很大程度上取决于数据的形状。例如,如果您有一个非常倾斜的类别(仅一个类别就涵盖了 99% 的产品),那么最好的解决方案必须考虑到这种倾斜。

关于sql - 多对多选择查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3762704/

相关文章:

sql - 如何在 T-SQL 中反转字符串中的值

ruby-on-rails - Ruby - 创建 postgresql 数据库的最佳方法

database - 摆脱插入触发器

mysql - 选择不在同一个表上的多个字段中

c# - asp.net 报告查看器错误基础知识 : operation not allowed

mysql - 关于 ORDER BY - MySQL

c# - 插入带有参数的多行 Sql Server

mysql - 如何使用变量在mysql中选择上个月?

带有 WHERE 子句的 JOIN 之后的 SQL WHERE 语句

SQL Server xml字符串解析varchar字段