高级SQL GROUP BY查询

Pat*_*h22 3 sql sql-server

我的Items表'Category','Category2'中有两列,两列包含基本相同的信息.如果我设计了数据库,我会为类别创建一个单独的表,并根据该表添加项目到类别,不幸的是我没有创建数据库,我现在无法更改它,但我认为仍然存在如何做我想做的事.

该表的一个例子如下所示

Category             Category2
------------------   -----------------
truck                full size - pickup
full size - pickup   truck
Sedan                Import - Sedan
Convertible          Domestic - Coupe
Run Code Online (Sandbox Code Playgroud)

我想运行一个查询来计算卡车,轿车,全尺寸 - 皮卡等的总数.我尝试了下面的查询,但它分别将两列分组

SELECT Category, Count(*) as Count
FROM Items
GROUP BY Category, Category2
Run Code Online (Sandbox Code Playgroud)

Amy*_*y B 14

在分组之前,只需将两个类别转储到一个列中.

SELECT Category, Count(*) as TheCount
FROM
(
  SELECT Category1 as Category
  FROM Items
  UNION ALL
  SELECT Category2
  FROM Items
) sub
GROUP BY Category
Run Code Online (Sandbox Code Playgroud)

  • 确保使用union all,因为这表明,union会给出错误的答案 (2认同)

ara*_*nid 7

想象一下,具有"category,category2"的行可以转换为两行(一行带有"category",一行带有"category2")来获得你想要的.你这样做是这样的:

SELECT items.category /* , other columns... */
FROM items
UNION ALL
SELECT items.category2 /* , other columns... */
FROM items
Run Code Online (Sandbox Code Playgroud)

所以你需要做的就是聚合这些:

SELECT category, count(*) FROM (
    SELECT items.category FROM items
    UNION ALL
    SELECT items.category2 FROM items
    ) expanded
GROUP BY category
Run Code Online (Sandbox Code Playgroud)

如果您的数据库支持,您也可以按照这样的阶段进行聚合:

with subcounts as (
  select items.category, items.category2, count(*) as subcount
  from items
  group by category, category2)
select category, sum(subagg) as finalcount from (
  select subcounts.category, sum(subcount) as subagg from subcounts group by category
  union all
  select subcounts.category2, sum(subcount) as subagg from subcounts group by category2
) combination
group by category
Run Code Online (Sandbox Code Playgroud)

这将仅限于主项目表的一次扫描,如果您只有少量类别,那就很好.您可以使用不支持"WITH ..."的数据库中的临时表来模拟相同的事情.

编辑:

我确信必须有另一种方法来做到这一点,而不扫描项目两次,并且有.好吧,这是PostgreSQL版本:

SELECT category, count(*) FROM (
  SELECT CASE selector WHEN 1 THEN category WHEN 2 THEN category2 END AS category
  FROM Items, generate_series(1,2) selector
) items_fixed GROUP BY category
Run Code Online (Sandbox Code Playgroud)

这里唯一的postgresql特定位是"generate_series(1,2)",它产生一个包含两行的"表" - 一行"1",一行"2".这是恕我直言,postgresql中最便捷的功能之一.当然,您也可以在SQL Server中实现类似的功能.或者你可以说"(选择1作为选择器联合全部选择2)".另一个选择是"(values(1),(2))series(selector)"虽然这个语法有多少是标准的,多少是postgres特有的,但我不确定.这两种方法都有一个优点,即给计划者一个只有两行的想法.

交叉连接此系列表项允许我们为每行项生成两个输出行.您甚至可以使用"items_fixed"子查询并使其成为一个视图 - 哪个btw与我倾向于尝试解决这些问题的过程相反.