从数据库

时间:2017-02-11 16:55:56

标签: sql sqlite

我有一个表projects,用户可以在其中输入新项目,并记录用户和date_added(以及其他字段):

|----|------------|--------------|
| id | user_added | date_added   |
|----|------------|--------------|
| 1  | 'person 1' | '2017-01-05' |
| 2  | 'person 2' | '2017-02-10' |
| 3  | 'person 3' | '2017-02-23' |
| 4  | 'person 1' | '2017-03-04' |
| 5  | 'person 3' | '2017-03-31' |
|----|------------|--------------|

我想知道是否以及如何通过添加项目的用户分组每月的项目数量。上表的预期输出:

|------------|---------|---------|---------|-----|
| user_added | 2017-01 | 2017-02 | 2017-03 | etc.|
|------------|---------|---------|---------|-----|
| 'person 1' |    1    |    0    |    1    | ... |
| 'person 2' |    0    |    1    |    0    | ... |
| 'person 3' |    0    |    1    |    1    | ... |
|------------|---------|---------|---------|-----|

3 个答案:

答案 0 :(得分:0)

不要将值放入列中。 SQL方式是每人每月一行:

select user_added, strftime(date_added, '%Y-%m') as yyyymm, count(*)
from t
group by user_added, strftime(date_added, '%Y-%m')
order by 1, 2;

这是返回结果的SQLish方式。您可以在应用程序中透视值。

在SQL中转动它们的问题是您无法处理任意数月。 SQL查询返回固定数量的列,其名称必须在查询中指定。

答案 1 :(得分:0)

如果你事先知道年月,你可以使用聚合来做这样的旋转:

select user_added,
    count(case 
            when ym = '2017-01'
                then 1
            end) "2017-01",
    count(case 
            when ym = '2017-02'
                then 1
            end) "2017-02",
    count(case 
            when ym = '2017-03'
                then 1
            end) "2017-03",
    . . .
from (
    select user_added,
        strftime(date_added, '%Y-%m') ym
    from your_table
    ) t
group by user_added;

如果没有,那么将年份保持在单列中,并将其与每个用户的计数一起保留:

select user_added,
    ym,
    count(*)
from (
    select user_added,
        strftime(date_added, '%Y-%m') ym
    from your_table
    ) t
group by user_added,
    ym;

答案 2 :(得分:0)

正如戈登·林诺夫所说 - 当你有一个固定数量的可能值可以转入时,你只能在数据库中进行转动 - 在你的情况下是年月组合。

如果您坚持使用3年月值,它会像这样工作(是的,您需要将年月值硬连接到列名称中):

WITH
-- input
projects(id,user_added,date_added) AS (
          SELECT 1  , 'person 1' , DATE '2017-01-05' 
UNION ALL SELECT 2  , 'person 2' , DATE '2017-02-10' 
UNION ALL SELECT 3  , 'person 3' , DATE '2017-02-23' 
UNION ALL SELECT 4  , 'person 1' , DATE '2017-03-04' 
UNION ALL SELECT 5  , 'person 3' , DATE '2017-03-31' 
)
,
-- vertical display
vertical_grouped AS (
SELECT
  user_added
, strftime(date_added,'%Y-%M') AS yearmonth
, COUNT(*)                     AS projcount
FROM projects
GROUP BY 
  user_added
, strftime(date_added,'%Y-%M') 
)
SELECT
  user_added
, IFNULL(SUM(CASE yearmonth WHEN '2017-01' THEN projcount END),0) AS "2017-01"
, IFNULL(SUM(CASE yearmonth WHEN '2017-02' THEN projcount END),0) AS "2017-02"
, IFNULL(SUM(CASE yearmonth WHEN '2017-03' THEN projcount END),0) AS "2017-03"
FROM vertical_grouped
GROUP BY
  user_added
;

user_added|2017-01|2017-02|2017-03
person 1  |      1|      0|      1
person 2  |      0|      1|      0
person 3  |      0|      1|      1