2015-10-07 3 views
1

У меня есть следующий запрос. Он работает так, как ожидалось. Но он имеет подзапрос. Есть ли способ его оптимизировать?Удалить подзапрос в группе по запросу

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.

+0

В чем причина этого подзапроса? –

+5

Я не вижу, как ваш запрос мог бы вернуть эти результаты с данными образца – Lamak

+0

, вам не хватает шага или чего-то - код не имеет смысла, а результаты меньше. – Hogan

ответ

3

Невозможно оптимизировать это, вы можете написать его по-другому, но это не будет быстрее. Вы можете переписать его так, но вы не можете переписать его, чтобы избежать подзапроса:

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

Достаточно честный. Я тоже не мог найти его. Но хотелось быть уверенным :) –

2

на основе редактирования вопроса ...

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

Это та же функциональность как подзапрос, если интервал между символами отличные (то есть ваши данные не включают в себя -

https://data.stackexchange.com/stackoverflow/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 

Если это не даст вам результат вы хотите, пожалуйста, объясните, почему

+0

Во-вторых, вы, вероятно, должны добавить 'DISTINCT' https://data.stackexchange.com/stackoverflow/query/372453 – lad2025

+1

Оба из тысяч запросов не дают отдельных строк столбцов Foo. Глядя на набор данных, предоставленный в первом посте, я хочу, чтобы он сказал: «a: 2, b: 1» говорит: «a: 1, a: 1, b: 1' –

+0

@ Snæbjørn в обоих случаях, где говорится« Foo, Bar, Baz' замените это на 'Foo'. Вероятно, это произойдет, если вы сделаете это изменение, если используете первый случай **, поэтому ** используйте функцию окна во втором случае. – Hogan

1

Отказ от ответственности:

Это чистый для удовольствия решение, он не на 100% процентов надежный и может не работать когда происходит столкновение. Я отправляю его только как свою попытку получить решение без подзапроса. Это не будет быстрее, поэтому, пожалуйста, не используйте его в производственных системах.

Я предполагаю, что в колонках может быть одно значение BarxorBaz.

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; 

EDIT:

Если ('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 

Любые мысли о том, как улучшить его или почему его «отстой» оценили.

Смежные вопросы