2013-09-13 5 views
0

У меня есть запрос как таковые (что не совсем работы, как предполагалось)Совокупной SQL группы подсчета на основе группы по

SELECT 
(CASE 
    WHEN str LIKE '%some_string%' THEN 's' 
    WHEN str LIKE '%some_string2%' THEN 's2' 
END) as str, 
COUNT(*) as num FROM Table WHERE 
str LIKE '%some_string%' or 
str LIKE '%some_string2%' 
group by str 

и таблица содержит такие вещи, как

|  str      | 
|------------------------------- | 
| "some_string_a;"    | 
| "some_string_b; some_else"  | 
| "some_string_c; some_else"  | 
| "some_else; some_string2a"  | 
| "some_string_c; some_string2b" | 

Как сделать Я получаю результат следующим образом?

|  str  | num | 
|---------------|--------| 
| s    | 4 | 
| s2   | 2 | 

Я в настоящее время я занижение, потому что строки 1,2,3 и 5 посчитаны как «some_string%» (и, следовательно, «S»), когда они на самом деле содержат оба.

+0

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

+0

@rio не могли бы вы проверить мой ответ? – Dhaval

+0

Сначала вы должны нормализовать свои данные. –

ответ

0

Попробуйте переключить порядок условий в инструкции CASE.

SELECT 
(CASE 
    WHEN str LIKE '%some_string2%' THEN 's2' 
    WHEN str LIKE '%some_string%' THEN 's' 
END) as str, 
COUNT(*) as num FROM Table WHERE 
str LIKE '%some_string%' or 
str LIKE '%some_string2%' 
group by str 
+0

Я не думаю, что обрабатывает случай «два экземпляра some_string в одной строке», хотя это была моя первоначальная мысль: p – eouw0o83hf

+0

Он не обрабатывал бы два экземпляра some_string в одной строке, вы правы. Но он решает проблему строки, считая слова s, когда она должна идти к s2. Чтобы справиться с проблемой, которую вы вызываете, я, вероятно, создаю UDF, который возвращает int числа раз, когда шаблон возникает в другой строке/строке. Тогда мы могли бы просто SUM те. –

1

мой обновленный ответ

SQL Fiddle

Попробуйте

CREATE table Table1 (str varchar(50)); 


    Insert into Table1(str) values('aaa'); 
    Insert into Table1(str) values('bbb'); 
    Insert into Table1(str) values('aaaaaaaaaa'); 
    Insert into Table1(str) values('bbbbbbbbbb'); 
    Insert into Table1(str) values('aaaaaaaaaaaaaaaa'); 
    Insert into Table1(str) values('aaabbbbb'); 
    Insert into Table1(str) values('ccccccccccccccc'); 


Select str , count(*) from 
(
    SELECT 
    (CASE 
    WHEN str LIKE '%bbb%' THEN 's2' 
    WHEN str LIKE '%aaa%' THEN 's'  
    END) as str 
    FROM Table1 WHERE 
    str LIKE '%aaa%' or 
    str LIKE '%bbb%' 
) as T group by str; -- will count in s2 means in a so s will be 3 and s2 is 3 
+0

Это не работает для случая. Вставьте значения Table1 (str) ('aaabbbbb'); – Rio

+0

, если я вставляю aaabbbb, в котором он должен рассчитывать, находится ли в s или s2. Я думаю, что по вашему мнению, он должен рассчитывать на s2, поэтому оба значения 3 в моем примере (после вставки aaabbbb) .. правильно ?? – Dhaval

+0

Он должен быть равен 3, но ваш SQLFiddle возвращает 3 и 2 (измените первую строку как aaabbbbb) – Rio

0

Вы могли бы сделать это.

SELECT SUM(IF(str LIKE '%some_string%',1,0)) AS s, 
     SUM(IF(str LIKE '%some_string2%',1,0)) AS s2 
FROM Table WHERE 
str LIKE '%some_string%' or 
str LIKE '%some_string2%' 
group by str; 
+0

Это создает дополнительные столбцы, я думаю, но тогда, я думаю, мне пришлось бы сортировать по s, s2, и я не знал бы заранее, какие столбцы больше похожи (чтобы он мог этот вид по s2, s лучше). – Rio

0

Вы хотите сгруппировать одним и тем же выражением в select:

SELECT (CASE WHEN str LIKE '%some_string%' THEN 's' 
      WHEN str LIKE '%some_string2%' THEN 's2' 
     END) as str, 
     COUNT(*) as num 
FROM Table 
WHERE str LIKE '%some_string%' or 
     str LIKE '%some_string2%' 
group by (CASE WHEN str LIKE '%some_string%' THEN 's' 
       WHEN str LIKE '%some_string2%' THEN 's2' 
      END); 

Некоторые базы данных позволяют псевдоним столбца (str), которые будут использоваться в group by, но не все. Вы более безопасны, используя полное выражение или используя подзапрос (как предлагает Dhaval). Тем не менее, я хотел бы написать:

select str, count(*) 
from (select (CASE WHEN str LIKE '%some_string%' THEN 's' 
        WHEN str LIKE '%some_string2%' THEN 's2' 
       END) as str 
     from table 
    ) t 
where str is not null 
group by str; 

Вам не придется повторять сравнения, потому что str получает значение NULL, когда он не соответствует ни.

+0

У меня возникают проблемы с группой (CASE WHEN str LIKE '% some_string%' THEN ' WHEN str LIKE'% some_string2% 'THEN' s2 ' END); немного. Мне нужно сделать Group by str, но group by (CASE WHEN str LIKE '% some_string%' THEN 's WHEN str LIKE'% some_string2% 'THEN' s2 ' END), поскольку str, похоже, не играет хорошо , – Rio

+0

Какая проблема? И какую базу данных вы используете? Это стандартный синтаксис ANSI. –

0

С Postgres, общее решение для n моделей может выглядеть следующим образом:

SELECT p.pattern, count((str1 LIKE '%' || p.pattern || '%') OR NULL) AS ct 
FROM (
    SELECT regexp_split_to_table(str, ';') AS str1 
    FROM tbl 
    ) x 
CROSS JOIN (
    VALUES ('some_string') 
     ,('some_string2') 
     -- more? 
    ) AS p(pattern) 
GROUP BY p.pattern 

Результат:

pattern  | ct 
--------------+---- 
some_string | 6 
some_string2 | 2 

-> SQLfiddle demo

  • Я предположить вы хотите сопоставить каждую часть строки, помеченной ;. Функция Postgres regexp_split_to_table() нормализует ваши данные таким образом.

  • Я также Предполагаю, что вы хотите считать каждое совпадение любым рисунком и не останавливаться после первого матча.

Заявление CASE приведет только к единственному совпадению и подавит остальное.Поэтому я предполагаю, что вы делаете не хотите это.

Вместо этого я перехожу к выражению VALUES, которое предоставляет как можно больше шаблонов. Очень удобно для общего использования. Вы можете использовать таблицу или подзапрос, чтобы предоставить шаблоны вместо выражения VALUES.

+0

Это изящное решение, но, к сожалению, данные на самом деле не такие чистые, поэтому; предположение фактически ломается. Спасибо хоть! – Rio

+0

Я могу ответить только на вопрос, как это дается. –

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