按查询删除组中的子查询

Remove subquery in group by query

我有以下查询。它按预期工作。但是它有一个子查询。有什么办法可以优化吗?

SELECT Foo,
       count(*)
FROM
  (SELECT Foo
   FROM MyTable
   GROUP BY Foo,
            Bar,
            Baz) AS Subquery
GROUP BY Foo

为了上下文

它正在处理的数据集如下:

| Foo | Bar | Baz |
|-----|-----|-----|
| a   | 1   |     |
| a   |     | 2   |
| b   | 3   |     |
| b   | 3   |     |

预期结果是:

| Foo | Count |
|-----|-------|
| a   | 2     |
| b   | 1     |

文字说明。或者尝试。

我想获得每个 Foo 的不同 Bar 和 Baz 的数量。

根据问题的编辑...

SELECT Foo, Count(distinct isnull(foo,'-')+isnull(bar,'-')+isnull(baz,'-'))
FROM MyTable
group by foo

如果空格字符不同(即您的数据不包括 -

,这与子查询的功能相同

https://data.stackexchange.com/Whosebug/query/372553/for-question-32992867


我想你想要这个:

SELECT Foo, count(*)
FROM MyTable
GROUP BY Foo, Bar, Baz

你可能想要这个:

SELECT Foo, Count(*) OVER (Partition By Foo, Bar, Baz)
FROM MyTable

如果这些没有给您想要的结果,请解释原因

免责声明:

这纯粹是为了好玩的解决方案,它不是 100% 可靠的,并且在发生碰撞时可能会失败。我 post 它只是因为我试图在没有子查询的情况下获得解决方案。它不会更快,所以请不要在生产系统中使用它。

我假设 Bar xor Baz.

列中可以有一个值

LiveDemo

CREATE TABLE #MyTable(Foo VARCHAR(100), Bar VARCHAR(10), Baz VARCHAR(10));

INSERT INTO #MyTable(Foo, Bar, Baz)
VALUES ('a', '1', NULL), ('a', NULL ,'2'), ('b', '3', NULL),
       ('a', '2', NULL), ('a', NULL ,'1'), ('b', '3', NULL),
       ('a', NULL, '2'), ('a', NULL ,'1'), ('b', '4', NULL),
       ('a', NULL, '1'), ('a', NULL ,'2'), ('b', '7', NULL);

SELECT Foo, COUNT(DISTINCT  
                  CAST(CHECKSUM(Bar, Baz) AS BIGINT) + 
                  CAST(CHECKSUM(Baz, Bar) AS BIGINT) +
                  CAST(CHECKSUM(REVERSE(Bar),REVERSE(Baz)) AS BIGINT) + 
                  CAST(CHECKSUM(REVERSE(Baz),REVERSE(Bar)) AS BIGINT)) 
FROM #MyTable
GROUP BY Foo;

编辑:

如果 ('a', NULL, 1)('a', 1, NULL) 应该不同,您需要使用:

LiveDemo2

SELECT Foo, COUNT(DISTINCT  
                  CAST(CHECKSUM(Bar, Baz) AS BIGINT) + 
                  CAST(CHECKSUM(REVERSE(Bar),REVERSE(Baz)) AS BIGINT))
FROM #MyTable
GROUP BY Foo

任何想法如何改进它或为什么它 "sucks" 赞赏。

没有办法优化它,你可以用不同的方式写它,但不会更快。可以这样改写,但是不能改写,避免subselect:

SELECT Foo,
       count(*)
FROM
  (SELECT distinct Foo, bar, baz
   FROM @t
   ) AS Subquery
GROUP BY Foo