2015-02-20 2 views
0

SQLite таблицы базы данных table1

user  command date  location 
---------- ---------- ---------- ---------- 
user1  cmd1  2015-01-01 xxxdeyyy 
user2  cmd1  2015-01-01 zzzfrxxx 
user3  cmd1  2015-01-01 yyyukzzz 
user1  cmd1  2015-01-01 xxxdezzz 
... 

Ожидаемый результат

Выход для where command='cmd1':Как мне группировать строки и столбцы в SQLite3?

month users_de users_fr users_es 
-------- -------- -------- -------- 
01  1  0  5 
02  2  0  0 
03  0  2  1 
04  5  0  15 
05  1  0  4 
06  11  1  2 
07  9  0  3 
08  1  0  5 
09  0  0  5 
10  0  0  0 
11  1  0  0 
12  1  4  5 

Он группируется по месяцам (от колонки date), а также сгруппированы по подстроке в месте (от столбец location).

Фактический выход

я могу добиться этого (в месте):

month users_de 
-------- -------- 
01  1  
02  2  
03  0  
...  
12  1  

используя этот запрос:

select strftime('%m',date) as month, count(distinct user) as users_de 
from table1 
where command='cmd1' and location like '%de%' 
group by strftime('%m',date); 

Я тогда повторить этот запрос для других местах (where ... and location='fr'):

month users_fr 
-------- -------- 
01  0  
02  0  
03  2  
... 
12  4  

и (where ... and location='es');

month users_es 
-------- -------- 
01  5 
02  0 
03  1 
... 
12  5 

Есть ли способ, чтобы иметь все users_xx столбцов в одной таблице (в качестве выходных данных из SQLite, а не через какую-либо внешнюю (вниз по течению) обработки)?

Я думаю об этом неправильно (группировка вместо подзапросов в верхней части select)?

+1

Вы можете использовать корпус для каждого местоположения –

ответ

0

Я думаю, что вы хотите условную агрегацию:

select strftime('%m',date) as month, 
     count(distinct CASE WHEN location like '%de%' THEN user END) as users_de, 
     count(distinct CASE WHEN location like '%fr%' THEN user END) as users__fr, 
     count(distinct CASE WHEN location like '%es%' THEN user END) as users_es 
from table1 
where command = 'cmd1' 
group by strftime('%m',date); 

Два примечания:

  • like возможно не является безопасным в этом контекст. У вас есть код страны, встроенный в строку, но символы «de», «es» или «fr» могут появляться в другом месте строки. Ваш вопрос не ясен в отношении лучшей логики для этого.
  • Вы должны указать год в строке даты, но ваш вопрос конкретно включает только месяц.
+0

Спасибо, это работает!ваши две (очень действительные) заметки: я могу быть уверен, что подстроки не появляются нигде в строке; однако в будущем ситуация может измениться, и я буду строить некоторые проверки (скорее всего, в парсере, подающем базу данных, в первую очередь). Про год ... сделано! 'STRFTIME ('% Y-% м', дата)' – phil

1

Вы можете использовать оператор case для соответствия каждому местоположению, а затем, если совпадение подсчитывает пользователя.

select strftime('%m',date) as month, 
      CASE WHEN location='de' THEN count(distinct user) END users-de, 
      CASE WHEN location='fr' THEN count(distinct user) END users-fr, 
      CASE WHEN location='es' THEN count(distinct user) END users-es, 
    from table1 
    where command='cmd1' 
    group by strftime('%m',date),location; 
+0

На самом деле, я действительно упростил свой пример. 'Location' - это строка, содержащая' de' или 'es' или' fr'. Используется ли 'CASE WHEN местоположение типа '% de%''? Что я могу сделать для 'group by location' (из-за' like '% de%' '? Почему он мне нужен в первую очередь? – phil

-2

Используя запрос, как это:

SELECT strftime('%m',date) AS month, 
     location, 
     count(distinct user) AS users-de, 
     count(distinct user) AS users-fr, 
     count(distinct user) AS users-es 
    FROM table1 
WHERE command='cmd1' GROUP BY strftime('%m', date), location; 
+0

Три счета имеют разные имена, но их значения одинаковы. –

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