Thread: Counting different strings (OK%, FB%) in same table, grouped by week number

Counting different strings (OK%, FB%) in same table, grouped by week number

From
Alexander Farber
Date:
Hello,

I have a table holding week numbers (as strings)
and user ids starting with OK, VK, FB, GG, MR, DE
(coming through diff. soc. networks to my site):

afarber@www:~> psql
psql (8.4.9)
Type "help" for help.

pref=> select * from pref_money;

           id            | money  |   yw
-------------------------+--------+---------
 OK19644992852           |      8 | 2010-44
 OK21807961329           |    114 | 2010-44
 FB1845091917            |    774 | 2010-44
 OK172682607383          |    -34 | 2010-44
 VK14831014              |     14 | 2010-44
 VK91770810              |   2368 | 2010-44
 DE8341                  |    795 | 2010-44
 VK99736508              |     97 | 2010-44

I'm trying to count those different users.

For one type of users (here Facebook) it's easy:


pref=> select yw, count(*) from pref_money
            where id like 'FB%' group by yw order by yw desc;

   yw    | count
---------+-------
 2012-08 |    32
 2012-07 |    32
 2012-06 |    37
 2012-05 |    46
 2012-04 |    41

But if I want to have a table displaying all users
(a column for "FB%", a column for "OK%", etc.) -
then I either have to perform a lot of copy-paste and
vim-editing or maybe someone can give me an advice?

I've reread the having-doc at
http://www.postgresql.org/docs/8.4/static/tutorial-agg.html
and still can't figure it out...

Thank you
Alex

Re: Counting different strings (OK%, FB%) in same table, grouped by week number

From
David Johnston
Date:
On Feb 22, 2012, at 15:36, Alexander Farber <alexander.farber@gmail.com> wrote:

> Hello,
>
> I have a table holding week numbers (as strings)
> and user ids starting with OK, VK, FB, GG, MR, DE
> (coming through diff. soc. networks to my site):
>
> afarber@www:~> psql
> psql (8.4.9)
> Type "help" for help.
>
> pref=> select * from pref_money;
>
>           id            | money  |   yw
> -------------------------+--------+---------
> OK19644992852           |      8 | 2010-44
> OK21807961329           |    114 | 2010-44
> FB1845091917            |    774 | 2010-44
> OK172682607383          |    -34 | 2010-44
> VK14831014              |     14 | 2010-44
> VK91770810              |   2368 | 2010-44
> DE8341                  |    795 | 2010-44
> VK99736508              |     97 | 2010-44
>
> I'm trying to count those different users.
>
> For one type of users (here Facebook) it's easy:
>
>
> pref=> select yw, count(*) from pref_money
>            where id like 'FB%' group by yw order by yw desc;
>
>   yw    | count
> ---------+-------
> 2012-08 |    32
> 2012-07 |    32
> 2012-06 |    37
> 2012-05 |    46
> 2012-04 |    41
>
> But if I want to have a table displaying all users
> (a column for "FB%", a column for "OK%", etc.) -
> then I either have to perform a lot of copy-paste and
> vim-editing or maybe someone can give me an advice?
>
> I've reread the having-doc at
> http://www.postgresql.org/docs/8.4/static/tutorial-agg.html
> and still can't figure it out...
>
> Thank you
> Alex
>

Straight SQL:

SELECT SUM(CASE WHEN id ~ '^FB' THEN 1 ELSE 0 END) AS fb_cnt, repeat for each known type (and I generally code one for
unknownas well). 

Depending of your use case building out the non-column version and pushing it into a PivotTable would work.  There is
alsoa crosstab module that you can use as well - though I have not used it myself. 



Re: Counting different strings (OK%, FB%) in same table, grouped by week number

From
Alexander Farber
Date:
Thank you David -

On Wed, Feb 22, 2012 at 9:56 PM, David Johnston <polobo@yahoo.com> wrote:
> SELECT SUM(CASE WHEN id ~ '^FB' THEN 1 ELSE 0 END) AS fb_cnt, repeat for each known type (and I generally code one
forunknown as well). 
>
> Depending of your use case building out the non-column version and pushing it into a PivotTable would work.  There is
alsoa crosstab module that you can use as well - though I have not used it myself. 
>

this works well, but I'm curious
how'd you count unknown users here?

pref=> SELECT yw,
SUM(CASE WHEN id ~ '^OK' THEN 1 ELSE 0 END) AS "Odnoklassniki",
SUM(CASE WHEN id ~ '^MR' THEN 1 ELSE 0 END) AS "Mail.ru",
SUM(CASE WHEN id ~ '^VK' THEN 1 ELSE 0 END) AS "Vkontakte",
SUM(CASE WHEN id ~ '^FB' THEN 1 ELSE 0 END) AS "Facebook",
SUM(CASE WHEN id ~ '^GG' THEN 1 ELSE 0 END) AS "Google",
SUM(CASE WHEN id ~ '^DE' THEN 1 ELSE 0 END) AS "Preferans.de",
count(*) AS "Total"
from pref_money group by yw order by yw desc;

   yw    | Odnoklassniki | Mail.ru | Vkontakte | Facebook | Google |
Preferans.de | Total
---------+---------------+---------+-----------+----------+--------+--------------+-------
 2012-08 |          2260 |     245 |       185 |       32 |      0 |
       314 |  3036
 2012-07 |          3074 |     338 |       267 |       32 |      0 |
       386 |  4097
 2012-06 |          3044 |     328 |       288 |       37 |      0 |
       393 |  4090
 2012-05 |          3092 |     347 |       268 |       46 |      2 |
       400 |  4155
 2012-04 |          3091 |     334 |       249 |       41 |      0 |
       402 |  4117

Re: Counting different strings (OK%, FB%) in same table, grouped by week number

From
Adrian Klaver
Date:
On 02/22/2012 12:36 PM, Alexander Farber wrote:
> Hello,
>
> I have a table holding week numbers (as strings)
> and user ids starting with OK, VK, FB, GG, MR, DE
> (coming through diff. soc. networks to my site):
>
> afarber@www:~>  psql
> psql (8.4.9)
> Type "help" for help.
>
> pref=>  select * from pref_money;
>
>             id            | money  |   yw
> -------------------------+--------+---------
>   OK19644992852           |      8 | 2010-44
>   OK21807961329           |    114 | 2010-44
>   FB1845091917            |    774 | 2010-44
>   OK172682607383          |    -34 | 2010-44
>   VK14831014              |     14 | 2010-44
>   VK91770810              |   2368 | 2010-44
>   DE8341                  |    795 | 2010-44
>   VK99736508              |     97 | 2010-44
>
> I'm trying to count those different users.
>
> For one type of users (here Facebook) it's easy:
>
>
> pref=>  select yw, count(*) from pref_money
>              where id like 'FB%' group by yw order by yw desc;
>
>     yw    | count
> ---------+-------
>   2012-08 |    32
>   2012-07 |    32
>   2012-06 |    37
>   2012-05 |    46
>   2012-04 |    41
>
> But if I want to have a table displaying all users
> (a column for "FB%", a column for "OK%", etc.) -
> then I either have to perform a lot of copy-paste and
> vim-editing or maybe someone can give me an advice?
>
> I've reread the having-doc at
> http://www.postgresql.org/docs/8.4/static/tutorial-agg.html
> and still can't figure it out...

How about?:

test=> \d storage_test
          Table "public.storage_test"
  Column  |         Type          | Modifiers
---------+-----------------------+-----------
  fld_1   | character varying     |
  fld_2   | character varying(10) |
  fld_3   | character(5)          |
  fld_int | integer

test=> SELECT * from storage_test ;
  fld_1 | fld_2 | fld_3 | fld_int
-------+-------+-------+---------
  FB001 | one   |       |       4
  FB002 | three |       |      10
  OK001 | three |       |       5
  OK002 | two   |       |       6
  VK001 | one   |       |       9
  VK002 | four  |       |       2

test=> SELECT substring(fld_1 from 1 for 2) as id_tag,fld_2, count(*)
from storage_test group by substring(fld_1 from 1 for 2),fld_2;
  id_tag | fld_2 | count
--------+-------+-------
  VK     | four  |     1
  VK     | one   |     1
  FB     | one   |     1
  FB     | three |     1
  OK     | two   |     1
  OK     | three |     1


>
> Thank you
> Alex
>



--
Adrian Klaver
adrian.klaver@gmail.com

Re: Counting different strings (OK%, FB%) in same table, grouped by week number

From
"David Johnston"
Date:
-----Original Message-----
From: Alexander Farber [mailto:alexander.farber@gmail.com]
Sent: Wednesday, February 22, 2012 4:10 PM
To: David Johnston
Cc: pgsql-general
Subject: Re: [GENERAL] Counting different strings (OK%, FB%) in same table,
grouped by week number

Thank you David -

On Wed, Feb 22, 2012 at 9:56 PM, David Johnston <polobo@yahoo.com> wrote:
> SELECT SUM(CASE WHEN id ~ '^FB' THEN 1 ELSE 0 END) AS fb_cnt, repeat for
each known type (and I generally code one for unknown as well).
>
> Depending of your use case building out the non-column version and pushing
it into a PivotTable would work.  There is also a crosstab module that you
can use as well - though I have not used it myself.
>

this works well, but I'm curious
how'd you count unknown users here?

pref=> SELECT yw,
SUM(CASE WHEN id ~ '^OK' THEN 1 ELSE 0 END) AS "Odnoklassniki", SUM(CASE
WHEN id ~ '^MR' THEN 1 ELSE 0 END) AS "Mail.ru", SUM(CASE WHEN id ~ '^VK'
THEN 1 ELSE 0 END) AS "Vkontakte", SUM(CASE WHEN id ~ '^FB' THEN 1 ELSE 0
END) AS "Facebook", SUM(CASE WHEN id ~ '^GG' THEN 1 ELSE 0 END) AS "Google",
SUM(CASE WHEN id ~ '^DE' THEN 1 ELSE 0 END) AS "Preferans.de",
count(*) AS "Total"
from pref_money group by yw order by yw desc;

   yw    | Odnoklassniki | Mail.ru | Vkontakte | Facebook | Google |
Preferans.de | Total
---------+---------------+---------+-----------+----------+--------+--------
------+-------
 2012-08 |          2260 |     245 |       185 |       32 |      0 |
       314 |  3036
 2012-07 |          3074 |     338 |       267 |       32 |      0 |
       386 |  4097
 2012-06 |          3044 |     328 |       288 |       37 |      0 |
       393 |  4090
 2012-05 |          3092 |     347 |       268 |       46 |      2 |
       400 |  4155
 2012-04 |          3091 |     334 |       249 |       41 |      0 |
       402 |  4117


----------------------------------------------------------------------------
-------

Brute Force:

When id does not match the expression "starts with one of the following:
'OK', 'MR', etc..."

CASE WHEN id !~ '^(OK|MR|VK|FB|GG|DE)' THEN 1 ELSE 0 END AS "Undefined"

David J.





Re: Counting different strings (OK%, FB%) in same table, grouped by week number

From
Kiriakos Georgiou
Date:
I'd code it more general to allow for any user type:

select
   yw, substr(id,1,2) as user_type, count(1)
from
   pref_money
group by
   yw, user_type

You can use some clever pivoting to get the user_types to be columns, but I see no need to waste db cycles.
You can get the report you want by one-pass processing of the above result set.

If you have mountains of data I'd precompute, before insert or during insert by a trigger, the user_type and store it
separately.

Kiriakos
http://www.mockbites.com



On Feb 22, 2012, at 3:36 PM, Alexander Farber wrote:

> Hello,
>
> I have a table holding week numbers (as strings)
> and user ids starting with OK, VK, FB, GG, MR, DE
> (coming through diff. soc. networks to my site):
>
> afarber@www:~> psql
> psql (8.4.9)
> Type "help" for help.
>
> pref=> select * from pref_money;
>
>           id            | money  |   yw
> -------------------------+--------+---------
> OK19644992852           |      8 | 2010-44
> OK21807961329           |    114 | 2010-44
> FB1845091917            |    774 | 2010-44
> OK172682607383          |    -34 | 2010-44
> VK14831014              |     14 | 2010-44
> VK91770810              |   2368 | 2010-44
> DE8341                  |    795 | 2010-44
> VK99736508              |     97 | 2010-44
>
> I'm trying to count those different users.
>
> For one type of users (here Facebook) it's easy:
>
>
> pref=> select yw, count(*) from pref_money
>            where id like 'FB%' group by yw order by yw desc;
>
>   yw    | count
> ---------+-------
> 2012-08 |    32
> 2012-07 |    32
> 2012-06 |    37
> 2012-05 |    46
> 2012-04 |    41
>
> But if I want to have a table displaying all users
> (a column for "FB%", a column for "OK%", etc.) -
> then I either have to perform a lot of copy-paste and
> vim-editing or maybe someone can give me an advice?
>
> I've reread the having-doc at
> http://www.postgresql.org/docs/8.4/static/tutorial-agg.html
> and still can't figure it out...
>
> Thank you
> Alex
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general