查询以获取每个类别 + 子类别的相同行数

Posted

技术标签:

【中文标题】查询以获取每个类别 + 子类别的相同行数【英文标题】:query to get equal number of rows per category + sub category 【发布时间】:2013-09-06 17:03:51 【问题描述】:

这就是我的 SQL 表结构的样子:

CREATE TABLE TempCategory
(
    Id BIGINT,
    Name VARCHAR(100)
)

CREATE TABLE TempSubCategory
(
    Id BIGINT,
    CategoryId BIGINT,
    Name VARCHAR(100)
)

CREATE TABLE TempProduct
(
    Id BIGINT,
    SubCategoryId BIGINT,
    Name VARCHAR(100)
)

http://sqlfiddle.com/#!3/2606fd/4

我正在编写一个 s-s-rS 报告,其中将类别显示为 x 轴,子类别显示为 y 轴,产品显示为数据。每个类别都有自己的子类别,因此我在每个行组的列组中显示子类别。

s-s-rS 报告不会为其未获取值的行绘制单元格。所以我的报告最终看起来像这样:

这是我当前查询的样子:

SELECT  TempCategory.Id, 'MainCategoryId',
        TempCategory.Name 'CategoryName',
        TempSubCategory.id 'SubCategoryId',
        TempSubCategory.Name 'SubCategory',
        TempProduct.Id 'ProductId',
        TempProduct.Name 'ProductName'
          FROM TempCategory
    INNER JOIN TempSubCategory
        ON TempCategory.Id = TempSubCategory.CategoryId
    INNER JOIN TempProduct
        ON TempSubCategory.Id = TempProduct.SubCategoryId

我要做的是修改查询,使其始终返回每个子类别组相同数量的行,以便在它确实具有数据的行中有空值或 0。

例如:类别 1 有 3 个子类别,最大产品数量在子类别 1 中,所以我希望查询返回 5(子类别 1 的最大产品数量) 具有主类别 1 的每个子类别的行。

对于类别 2,每个子类别将返回 2 行,因为最大数量的产品属于子类别 2。

是否可以在 SQL 中执行,或者在 s-s-rS 报告中是否有其他方法?

--更新--

这是一个带有 ProductName 行组的表

这是带有 SubCategory 列组的矩阵

这是一个带有产品名称行组的表格

【问题讨论】:

您能否在设计器模式下提供报表的屏幕截图?只是为了了解 tablix 本身所涉及的分组以及所有内容如何组合在一起。 另外,在你的实际数据中,像Cat1SubCat1Product1Cat1SubCat1Product1这样的产品之间是否有任何关系——它们在同一行,但列中的产品可以按任何顺序排列,它们与相邻的列有什么共同点吗? @IanPreston:我已经用设计模式屏幕截图更新了这个问题。不,两种产品之间没有关系。它们是子类别的子类别。 【参考方案1】:

对,这是一种(迂回)的做法:

with numbers as -- create lazy numbers table; feel free to replace with a proper one
(
  select distinct number
  from master..spt_values
  where number between 1 and 100
)
, rowCounts as
(
  select Category = tc.Name
    , SubCategory = tsc.Name
    , SubCategoryId = tsc.Id
    , MaxSubCatRows = count(1)
  from TempCategory tc
    inner join TempSubCategory tsc on tc.Id = tsc.CategoryId
    inner join TempProduct p on tsc.Id = p.SubCategoryId
  group by tc.Name
    , tsc.Name
    , tsc.Id
)
, maxRowCountPerGroup as
(
  select Category
    , MaxSubCatRows = max(MaxSubCatRows)
  from rowCounts
  group by Category
)
, allCats as
(
  select rc.Category
    , rc.SubCategory
    , rc.SubCategoryId
    , n.number
  from rowCounts rc
    inner join maxRowCountPerGroup mr on rc.Category = mr.Category
    cross apply (select number
                 from numbers
                 where number between 1 and mr.MaxSubCatRows) n
)
, orderedProducts as
(
  select *
    , productRowNumber = row_number() over (partition by SubCategoryId
                                            order by Id)
  from TempProduct
)
select c.Category
  , c.SubCategory
  , Product = p.Name
from allCats c
  left join orderedProducts p on c.subCategoryId = p.subCategoryId
    and c.number = p.productRowNumber
order by c.Category
  , c.SubCategory
  , case when p.Name is null then 1 else 0 end -- nulls last
  , p.Name

SQL Fiddle with demo.

所以...这是做什么的:

获取每个类别/子类别组合的行数 获取每组这些行数的最大值 使用数字表为每个表创建 n 占位符行 类别/子类别组合,其中n 是该类别的最大值 从上面 为子类别中的每个产品分配行号 左加入我们的类别占位符行到我们订购的产品

现在我们有了所需的行数,包括填充 s-s-rS 报告所需的 NULL 行。

剩下的就是将其应用于报表数据集;坐下来欣赏出现的额外行。

【讨论】:

非常感谢。非常感谢您花时间和精力将这些放在一起。

以上是关于查询以获取每个类别 + 子类别的相同行数的主要内容,如果未能解决你的问题,请参考以下文章

从具有类别和子类别的表中进行选择的 SQL 查询

获取类别和子类别的所有产品(rails,awesome_nested_set)

单词统计:对程序设计语言源文件统计字符数单词数行数,统计结果以指定格式输出到默认文件中

获取所有属于子类别的文章 多对多 Laravel

如何使用 EF Core Code-First 创建具有子类别的类别表? [复制]

mysql查询以获取列中每个元素的计数