One more default sorting order ("grouping").
[usenet/newsstats.git] / bin / groupstats.pl
CommitLineData
3f817eb4 1#! /usr/bin/perl
2832c235
TH
2#
3# groupstats.pl
4#
5# This script will get statistical data on newgroup usage
d3b6810d 6# from a database.
dfc2b81c 7#
2832c235
TH
8# It is part of the NewsStats package.
9#
07c0b258 10# Copyright (c) 2010-2013 Thomas Hochstein <thh@inter.net>
2832c235 11#
dfc2b81c 12# It can be redistributed and/or modified under the same terms under
2832c235
TH
13# which Perl itself is published.
14
15BEGIN {
16 our $VERSION = "0.01";
17 use File::Basename;
2ad99c20
TH
18 # we're in .../bin, so our module is in ../lib
19 push(@INC, dirname($0).'/../lib');
2832c235
TH
20}
21use strict;
3f817eb4 22use warnings;
2832c235 23
edd250f2 24use NewsStats qw(:DEFAULT :TimePeriods :Output :SQLHelper ReadGroupList);
2832c235
TH
25
26use DBI;
edd250f2
TH
27use Getopt::Long qw(GetOptions);
28Getopt::Long::config ('bundling');
2832c235
TH
29
30################################# Main program #################################
31
32### read commandline options
edd250f2
TH
33my ($OptBoundType,$OptCaptions,$OptCheckgroupsFile,$OptComments,
34 $OptFileTemplate,$OptFormat,$OptGroupBy,$OptGroupsDB,$LowBound,$OptMonth,
23ab67a0 35 $OptNewsgroups,$OptOrderBy,$OptReportType,$OptSums,$UppBound,$OptConfFile);
edd250f2
TH
36GetOptions ('b|boundary=s' => \$OptBoundType,
37 'c|captions!' => \$OptCaptions,
38 'checkgroups=s' => \$OptCheckgroupsFile,
39 'comments!' => \$OptComments,
40 'filetemplate=s' => \$OptFileTemplate,
41 'f|format=s' => \$OptFormat,
42 'g|group-by=s' => \$OptGroupBy,
43 'groupsdb=s' => \$OptGroupsDB,
44 'l|lower=i' => \$LowBound,
45 'm|month=s' => \$OptMonth,
46 'n|newsgroups=s' => \$OptNewsgroups,
47 'o|order-by=s' => \$OptOrderBy,
48 'r|report=s' => \$OptReportType,
49 's|sums!' => \$OptSums,
50 'u|upper=i' => \$UppBound,
23ab67a0 51 'conffile=s' => \$OptConfFile,
edd250f2
TH
52 'h|help' => \&ShowPOD,
53 'V|version' => \&ShowVersion) or exit 1;
54# parse parameters
55# $OptComments defaults to TRUE
56$OptComments = 1 if (!defined($OptComments));
57# force --nocomments when --filetemplate is used
58$OptComments = 0 if ($OptFileTemplate);
59# parse $OptBoundType
60if ($OptBoundType) {
61 if ($OptBoundType =~ /level/i) {
62 $OptBoundType = 'level';
63 } elsif ($OptBoundType =~ /av(era)?ge?/i) {
64 $OptBoundType = 'average';
65 } elsif ($OptBoundType =~ /sums?/i) {
66 $OptBoundType = 'sum';
67 } else {
68 $OptBoundType = 'default';
69 }
70}
71# parse $OptReportType
72if ($OptReportType) {
73 if ($OptReportType =~ /av(era)?ge?/i) {
74 $OptReportType = 'average';
75 } elsif ($OptReportType =~ /sums?/i) {
76 $OptReportType = 'sum';
77 } else {
78 $OptReportType = 'default';
79 }
80}
81# read list of newsgroups from --checkgroups
82# into a hash reference
83my $ValidGroups = &ReadGroupList($OptCheckgroupsFile) if $OptCheckgroupsFile;
2832c235
TH
84
85### read configuration
23ab67a0 86my %Conf = %{ReadConfig($OptConfFile)};
2832c235
TH
87
88### override configuration via commandline options
89my %ConfOverride;
edd250f2 90$ConfOverride{'DBTableGrps'} = $OptGroupsDB if $OptGroupsDB;
2832c235
TH
91&OverrideConfig(\%Conf,\%ConfOverride);
92
f2ddfd8a
TH
93### init database
94my $DBHandle = InitDB(\%Conf,1);
95
edd250f2
TH
96### get time period and newsgroups, prepare SQL 'WHERE' clause
97# get time period
98# and set caption for output and expression for SQL 'WHERE' clause
99my ($CaptionPeriod,$SQLWherePeriod) = &GetTimePeriod($OptMonth);
100# bail out if --month is invalid
101&Bleat(2,"--month option has an invalid format - ".
102 "please use 'YYYY-MM', 'YYYY-MM:YYYY-MM' or 'ALL'!") if !$CaptionPeriod;
103# get list of newsgroups and set expression for SQL 'WHERE' clause
104# with placeholders as well as a list of newsgroup to bind to them
c30822b4
TH
105my ($SQLWhereNewsgroups,@SQLBindNewsgroups);
106if ($OptNewsgroups) {
107 ($SQLWhereNewsgroups,@SQLBindNewsgroups) = &SQLGroupList($OptNewsgroups);
108 # bail out if --newsgroups is invalid
109 &Bleat(2,"--newsgroups option has an invalid format!")
110 if !$SQLWhereNewsgroups;
111}
edd250f2
TH
112
113### build SQL WHERE clause (and HAVING clause, if needed)
114my ($SQLWhereClause,$SQLHavingClause);
115# $OptBoundType 'level'
116if ($OptBoundType and $OptBoundType ne 'default') {
117 $SQLWhereClause = SQLBuildClause('where',$SQLWherePeriod,
118 $SQLWhereNewsgroups,&SQLHierarchies($OptSums));
119 $SQLHavingClause = SQLBuildClause('having',&SQLSetBounds($OptBoundType,
120 $LowBound,$UppBound));
121# $OptBoundType 'threshold' / 'default' or none
f2ddfd8a 122} else {
edd250f2
TH
123 $SQLWhereClause = SQLBuildClause('where',$SQLWherePeriod,
124 $SQLWhereNewsgroups,&SQLHierarchies($OptSums),
125 &SQLSetBounds('default',$LowBound,$UppBound));
126}
2832c235 127
edd250f2 128### get sort order and build SQL 'ORDER BY' clause
ea91003a
TH
129# force to 'month' for $OptReportType 'average' or 'sum'
130$OptGroupBy = 'month' if ($OptReportType and $OptReportType ne 'default');
edd250f2
TH
131# default to 'newsgroup' for $OptBoundType 'level' or 'average'
132$OptGroupBy = 'newsgroup' if (!$OptGroupBy and
133 $OptBoundType and $OptBoundType ne 'default');
ea91003a
TH
134# default to 'newsgroup' if $OptGroupBy is not set and
135# just one newsgroup is requested, but more than one month
136$OptGroupBy = 'newsgroup' if (!$OptGroupBy and
137 $OptMonth =~ /:/ and $OptNewsgroups !~ /[:*%]/);
edd250f2 138# parse $OptGroupBy to $GroupBy, create ORDER BY clause $SQLOrderClause
ea91003a 139# if $OptGroupBy is still not set, SQLSortOrder() will default to 'month'
edd250f2
TH
140my ($GroupBy,$SQLOrderClause) = SQLSortOrder($OptGroupBy, $OptOrderBy);
141# $GroupBy will contain 'month' or 'newsgroup' (parsed result of $OptGroupBy)
142# set it to 'month' or 'key' for OutputData()
143$GroupBy = ($GroupBy eq 'month') ? 'month' : 'key';
144
145### get report type and build SQL 'SELECT' query
146my $SQLSelect;
147my $SQLGroupClause = '';
148my $Precision = 0; # number of digits right of decimal point for output
149if ($OptReportType and $OptReportType ne 'default') {
150 $SQLGroupClause = 'GROUP BY newsgroup';
151 # change $SQLOrderClause: replace everything before 'postings'
152 $SQLOrderClause =~ s/BY.+postings/BY postings/;
153 if ($OptReportType eq 'average') {
154 $SQLSelect = "'All months',newsgroup,AVG(postings)";
155 $Precision = 2;
156 # change $SQLOrderClause: replace 'postings' with 'AVG(postings)'
157 $SQLOrderClause =~ s/postings/AVG(postings)/;
158 } elsif ($OptReportType eq 'sum') {
159 $SQLSelect = "'All months',newsgroup,SUM(postings)";
160 # change $SQLOrderClause: replace 'postings' with 'SUM(postings)'
161 $SQLOrderClause =~ s/postings/SUM(postings)/;
162 }
163 } else {
164 $SQLSelect = 'month,newsgroup,postings';
2832c235
TH
165};
166
edd250f2
TH
167### get length of longest newsgroup name delivered by query
168### for formatting purposes
169my $Field = ($GroupBy eq 'month') ? 'newsgroup' : 'month';
b342fcf0
TH
170my ($MaxLength,$MaxValLength) = &GetMaxLength($DBHandle,$Conf{'DBTableGrps'},
171 $Field,'postings',$SQLWhereClause,
172 $SQLHavingClause,
173 @SQLBindNewsgroups);
edd250f2
TH
174
175### build and execute SQL query
176my ($DBQuery);
177# special query preparation for $OptBoundType 'level', 'average' or 'sums'
178if ($OptBoundType and $OptBoundType ne 'default') {
179 # prepare and execute first query:
180 # get list of newsgroups meeting level conditions
181 $DBQuery = $DBHandle->prepare(sprintf('SELECT newsgroup FROM %s.%s %s '.
182 'GROUP BY newsgroup %s',
183 $Conf{'DBDatabase'},$Conf{'DBTableGrps'},
184 $SQLWhereClause,$SQLHavingClause));
185 $DBQuery->execute(@SQLBindNewsgroups)
186 or &Bleat(2,sprintf("Can't get groups data for %s from %s.%s: %s\n",
187 $CaptionPeriod,$Conf{'DBDatabase'},$Conf{'DBTableGrps'},
188 $DBI::errstr));
b802bc3d
TH
189 # add newsgroups to a comma-seperated list ready for IN(...) query
190 my $GroupList;
191 while (my ($Newsgroup) = $DBQuery->fetchrow_array) {
edd250f2 192 $GroupList .= ',' if $GroupList;
b802bc3d
TH
193 $GroupList .= "'$Newsgroup'";
194 };
edd250f2
TH
195 # enhance $WhereClause
196 if ($GroupList) {
197 $SQLWhereClause = SQLBuildClause('where',$SQLWhereClause,
198 sprintf('newsgroup IN (%s)',$GroupList));
199 } else {
200 # condition cannot be satisfied;
201 # force query to fail by adding '0=1'
202 $SQLWhereClause = SQLBuildClause('where',$SQLWhereClause,'0=1');
203 }
204}
205
206# prepare query
207$DBQuery = $DBHandle->prepare(sprintf('SELECT %s FROM %s.%s %s %s %s',
208 $SQLSelect,
209 $Conf{'DBDatabase'},$Conf{'DBTableGrps'},
c30822b4
TH
210 $SQLWhereClause,$SQLGroupClause,
211 $SQLOrderClause));
2832c235
TH
212
213# execute query
edd250f2
TH
214$DBQuery->execute(@SQLBindNewsgroups)
215 or &Bleat(2,sprintf("Can't get groups data for %s from %s.%s: %s\n",
216 $CaptionPeriod,$Conf{'DBDatabase'},$Conf{'DBTableGrps'},
217 $DBI::errstr));
218
219### output results
220# set default to 'pretty'
221$OptFormat = 'pretty' if !$OptFormat;
222# print captions if --caption is set
223if ($OptCaptions && $OptComments) {
224 # print time period with report type
225 my $CaptionReportType= '(number of postings for each month)';
226 if ($OptReportType and $OptReportType ne 'default') {
227 $CaptionReportType= '(average number of postings for each month)'
228 if $OptReportType eq 'average';
229 $CaptionReportType= '(number of all postings for that time period)'
230 if $OptReportType eq 'sum';
231 }
232 printf("# ----- Report for %s %s\n",$CaptionPeriod,$CaptionReportType);
233 # print newsgroup list if --newsgroups is set
234 printf("# ----- Newsgroups: %s\n",join(',',split(/:/,$OptNewsgroups)))
235 if $OptNewsgroups;
236 # print boundaries, if set
237 my $CaptionBoundary= '(counting only month fulfilling this condition)';
238 if ($OptBoundType and $OptBoundType ne 'default') {
239 $CaptionBoundary= '(every single month)' if $OptBoundType eq 'level';
240 $CaptionBoundary= '(on average)' if $OptBoundType eq 'average';
241 $CaptionBoundary= '(all month summed up)' if $OptBoundType eq 'sum';
242 }
243 printf("# ----- Threshold: %s %s x %s %s %s\n",
244 $LowBound ? $LowBound : '',$LowBound ? '=>' : '',
245 $UppBound ? '<=' : '',$UppBound ? $UppBound : '',$CaptionBoundary)
246 if ($LowBound or $UppBound);
247 # print primary and secondary sort order
248 printf("# ----- Grouped by %s (%s), sorted %s%s\n",
249 ($GroupBy eq 'month') ? 'Months' : 'Newsgroups',
250 ($OptGroupBy and $OptGroupBy =~ /-?desc$/i) ? 'descending' : 'ascending',
251 ($OptOrderBy and $OptOrderBy =~ /posting/i) ? 'by number of postings ' : '',
252 ($OptOrderBy and $OptOrderBy =~ /-?desc$/i) ? 'descending' : 'ascending');
253}
23ab67a0 254
edd250f2
TH
255# output data
256&OutputData($OptFormat,$OptComments,$GroupBy,$Precision,
257 $OptCheckgroupsFile ? $ValidGroups : '',
b342fcf0 258 $OptFileTemplate,$DBQuery,$MaxLength,$MaxValLength);
2832c235
TH
259
260### close handles
261$DBHandle->disconnect;
262
263__END__
264
265################################ Documentation #################################
266
267=head1 NAME
268
269groupstats - create reports on newsgroup usage
270
271=head1 SYNOPSIS
272
23ab67a0 273B<groupstats> [B<-Vhcs> B<--comments>] [B<-m> I<YYYY-MM>[:I<YYYY-MM>] | I<all>] [B<-n> I<newsgroup(s)>] [B<--checkgroups> I<checkgroups file>] [B<-r> I<report type>] [B<-l> I<lower boundary>] [B<-u> I<upper boundary>] [B<-b> I<boundary type>] [B<-g> I<group by>] [B<-o> I<order by>] [B<-f> I<output format>] [B<--filetemplate> I<filename template>] [B<--groupsdb> I<database table>] [--conffile I<filename>]
2832c235
TH
274
275=head1 REQUIREMENTS
276
edd250f2 277See L<doc/README>.
2832c235
TH
278
279=head1 DESCRIPTION
280
281This script create reports on newsgroup usage (number of postings per
282group per month) taken from result tables created by
edd250f2 283B<gatherstats.pl>.
2832c235 284
edd250f2 285=head2 Features and options
2832c235 286
edd250f2 287=head3 Time period and newsgroups
2832c235 288
edd250f2
TH
289The time period to act on defaults to last month; you can assign another
290time period or a single month (or drop all time constraints) via the
291B<--month> option (see below).
2832c235 292
edd250f2
TH
293B<groupstats> will process all newsgroups by default; you can limit
294processing to only some newsgroups by supplying a list of those groups via
295B<--newsgroups> option (see below). You can include hierarchy levels in
296the output by adding the B<--sums> switch (see below). Optionally
297newsgroups not present in a checkgroups file can be excluded from output,
298sse B<--checkgroups> below.
299
300=head3 Report type
301
302You can choose between different B<--report> types: postings per month,
303average postings per month or all postings summed up; for details, see
304below.
305
306=head3 Upper and lower boundaries
307
308Furthermore you can set an upper and/or lower boundary to exclude some
309results from output via the B<--lower> and B<--upper> options,
310respectively. By default, all newsgroups with more and/or less postings
311per month will be excluded from the result set (i.e. not shown and not
312considered for average and sum reports). You can change the meaning of
313those boundaries with the B<--boundary> option. For details, please see
314below.
315
316=head3 Sorting and formatting the output
317
318By default, all results are grouped by month; you can group results by
319newsgroup instead via the B<--groupy-by> option. Within those groups, the
320list of newsgroups (or months) is sorted alphabetically (or
321chronologically, respectively) ascending. You can change that order (and
322sort by number of postings) with the B<--order-by> option. For details and
323exceptions, please see below.
324
325The results will be formatted as a kind of table; you can change the
326output format to a simple list or just a list of newsgroups and number of
327postings with the B<--format> option. Captions will be added by means of
328the B<--caption> option; all comments (and captions) can be supressed by
329using B<--nocomments>.
330
331Last but not least you can redirect all output to a number of files, e.g.
332one for each month, by submitting the B<--filetemplate> option, see below.
333Captions and comments are automatically disabled in this case.
2832c235
TH
334
335=head2 Configuration
336
f2ddfd8a 337B<groupstats> will read its configuration from F<newsstats.conf>
2832c235
TH
338which should be present in the same directory via Config::Auto.
339
340See doc/INSTALL for an overview of possible configuration options.
341
edd250f2 342You can override some configuration options via the B<--groupsdb> option.
2832c235
TH
343
344=head1 OPTIONS
345
346=over 3
347
edd250f2 348=item B<-V>, B<--version>
2832c235 349
edd250f2 350Print out version and copyright information and exit.
2832c235 351
edd250f2 352=item B<-h>, B<--help>
2832c235
TH
353
354Print this man page and exit.
355
dfc2b81c 356=item B<-m>, B<--month> I<YYYY-MM[:YYYY-MM]|all>
2832c235 357
edd250f2
TH
358Set processing period to a single month in YYYY-MM format or to a time
359period between two month in YYYY-MM:YYYY-MM format (two month, separated
360by a colon). By using the keyword I<all> instead, you can set no
361processing period to process the whole database.
2832c235 362
edd250f2 363=item B<-n>, B<--newsgroups> I<newsgroup(s)>
2832c235
TH
364
365Limit processing to a certain set of newsgroups. I<newsgroup(s)> can
366be a single newsgroup name (de.alt.test), a newsgroup hierarchy
367(de.alt.*) or a list of either of these, separated by colons, for
368example
369
370 de.test:de.alt.test:de.newusers.*
371
edd250f2 372=item B<-s>, B<--sums|--nosums> (sum per hierarchy level)
2832c235 373
edd250f2
TH
374Include "virtual" groups for every hierarchy level in output, for
375example:
2832c235 376
edd250f2
TH
377 de.alt.ALL 10
378 de.alt.test 5
379 de.alt.admin 7
2832c235 380
edd250f2 381See the B<gatherstats> man page for details.
2832c235 382
edd250f2 383=item B<--checkgroups> I<filename>
2832c235 384
edd250f2
TH
385Restrict output to those newgroups present in a file in checkgroups format
386(one newgroup name per line; everything after the first whitespace on each
387line is ignored). All other newsgroups will be removed from output.
2832c235 388
95d9fe2c
TH
389Contrary to B<gatherstats>, I<filename> is not a template, but refers to
390a single file in checkgroups format.
391
edd250f2 392=item B<-r>, B<--report> I<default|average|sums>
2832c235 393
edd250f2 394Choose the report type: I<default>, I<average> or I<sums>
2832c235 395
edd250f2
TH
396By default, B<groupstats> will report the number of postings for each
397newsgroup in each month. But it can also report the average number of
398postings per group for all months or the total sum of postings per group
399for all months.
2832c235 400
edd250f2
TH
401For report types I<average> and I<sums>, the B<group-by> option has no
402meaning and will be silently ignored (see below).
2832c235 403
edd250f2 404=item B<-l>, B<--lower> I<lower boundary>
2832c235 405
edd250f2 406Set the lower boundary. See B<--boundary> below.
2832c235 407
edd250f2 408=item B<-l>, B<--upper> I<upper boundary>
2832c235 409
edd250f2 410Set the upper boundary. See B<--boundary> below.
2832c235 411
edd250f2
TH
412=item B<-b>, B<--boundary> I<boundary type>
413
414Set the boundary type to one of I<default>, I<level>, I<average> or
415I<sums>.
416
417By default, all newsgroups with more postings per month than the upper
418boundary and/or less postings per month than the lower boundary will be
419excluded from further processing. For the default report that means each
420month only newsgroups with a number of postings between the boundaries
421will be displayed. For the other report types, newsgroups with a number of
422postings exceeding the boundaries in all (!) months will not be
423considered.
424
425For example, lets take a list of newsgroups like this:
426
427 ----- 2012-01:
428 de.comp.datenbanken.misc 6
429 de.comp.datenbanken.ms-access 84
430 de.comp.datenbanken.mysql 88
431 ----- 2012-02:
432 de.comp.datenbanken.misc 8
433 de.comp.datenbanken.ms-access 126
434 de.comp.datenbanken.mysql 21
435 ----- 2012-03:
436 de.comp.datenbanken.misc 24
437 de.comp.datenbanken.ms-access 83
438 de.comp.datenbanken.mysql 36
439
440With C<groupstats --month 2012-01:2012-03 --lower 25 --report sums>,
441you'll get the following result:
2832c235 442
edd250f2
TH
443 ----- All months:
444 de.comp.datenbanken.ms-access 293
445 de.comp.datenbanken.mysql 124
2832c235 446
edd250f2
TH
447de.comp.datenbanken.misc has not been considered even though it has 38
448postings in total, because it has less than 25 postings in every single
95d9fe2c
TH
449month. If you want to list all newsgroups with more than 25 postings
450I<in total>, you'll have to set the boundary type to I<sum>, see below.
628a183c 451
edd250f2
TH
452A boundary type of I<level> will show only those newsgroups - at all -
453that satisfy the boundaries in each and every single month. With the above
454list of newsgroups and
455C<groupstats --month 2012-01:2012-03 --lower 25 --boundary level --report sums>,
456you'll get this result:
2832c235 457
edd250f2
TH
458 ----- All months:
459 de.comp.datenbanken.ms-access 293
2832c235 460
edd250f2 461de.comp.datenbanken.mysql has not been considered because it had less than
95d9fe2c 46225 postings in 2012-02 (only).
2832c235 463
edd250f2 464You can use that to get a list of newsgroups that have more (or less) then
95d9fe2c 465x postings in every month during the whole reporting period.
2832c235 466
edd250f2
TH
467A boundary type of I<average> will show only those newsgroups - at all -that
468satisfy the boundaries on average. With the above list of newsgroups and
469C<groupstats --month 2012-01:2012-03 --lower 25 --boundary avg --report sums>,
470you'll get this result:
78389b28 471
edd250f2
TH
472 ----- All months:
473 de.comp.datenbanken.ms-access 293
474 de.comp.datenbanken.mysql 145
2832c235 475
edd250f2 476The average number of postings in the three groups is:
2832c235 477
edd250f2
TH
478 de.comp.datenbanken.misc 12.67
479 de.comp.datenbanken.ms-access 97.67
480 de.comp.datenbanken.mysql 48.33
2832c235 481
edd250f2
TH
482Last but not least, a boundary type of I<sums> will show only those
483newsgroups - at all - that satisfy the boundaries with the total sum of
484all postings during the reporting period. With the above list of
485newsgroups and
486C<groupstats --month 2012-01:2012-03 --lower 25 --boundary sum --report sums>,
487you'll finally get this result:
2832c235 488
edd250f2
TH
489 ----- All months:
490 de.comp.datenbanken.misc 38
491 de.comp.datenbanken.ms-access 293
492 de.comp.datenbanken.mysql 145
2832c235 493
2832c235 494
edd250f2 495=item B<-g>, B<--group-by> I<month[-desc]|newsgroups[-desc]>
2832c235 496
edd250f2
TH
497By default, all results are grouped by month, sorted chronologically in
498ascending order, like this:
78389b28 499
edd250f2
TH
500 ----- 2012-01:
501 de.comp.datenbanken.ms-access 84
502 de.comp.datenbanken.mysql 88
503 ----- 2012-02:
504 de.comp.datenbanken.ms-access 126
505 de.comp.datenbanken.mysql 21
78389b28 506
edd250f2
TH
507The results can be grouped by newsgroups instead via
508B<--group-by> I<newsgroup>:
509
510 ----- de.comp.datenbanken.ms-access:
511 2012-01 84
512 2012-02 126
513 ----- de.comp.datenbanken.mysql:
514 2012-01 88
515 2012-02 21
516
517By appending I<-desc> to the group-by option parameter, you can reverse
518the sort order - e.g. B<--group-by> I<month-desc> will give:
519
520 ----- 2012-02:
521 de.comp.datenbanken.ms-access 126
522 de.comp.datenbanken.mysql 21
523 ----- 2012-01:
524 de.comp.datenbanken.ms-access 84
525 de.comp.datenbanken.mysql 88
526
527Average and sums reports (see above) will always be grouped by months;
528this option will therefore be ignored.
529
530=item B<-o>, B<--order-by> I<default[-desc]|postings[-desc]>
531
532Within each group (a single month or single newsgroup, see above), the
533report will be sorted by newsgroup names in ascending alphabetical order
534by default. You can change the sort order to descending or sort by number
535of postings instead.
536
537=item B<-f>, B<--format> I<pretty|list|dump>
538
539Select the output format, I<pretty> being the default:
540
541 ----- 2012-01:
542 de.comp.datenbanken.ms-access 84
543 de.comp.datenbanken.mysql 88
544 ----- 2012-02:
545 de.comp.datenbanken.ms-access 126
546 de.comp.datenbanken.mysql 21
547
548I<list> format looks like this:
549
550 2012-01 de.comp.datenbanken.ms-access 84
551 2012-01 de.comp.datenbanken.mysql 88
552 2012-02 de.comp.datenbanken.ms-access 126
553 2012-02 de.comp.datenbanken.mysql 21
554
555And I<dump> format looks like this:
556
557 # 2012-01:
558 de.comp.datenbanken.ms-access 84
559 de.comp.datenbanken.mysql 88
560 # 2012-02:
561 de.comp.datenbanken.ms-access 126
562 de.comp.datenbanken.mysql 21
563
564You can remove the comments by using B<--nocomments>, see below.
565
566=item B<-c>, B<--captions|--nocaptions>
567
568Add captions to output, like this:
569
570 ----- Report for 2012-01 to 2012-02 (number of postings for each month)
571 ----- Newsgroups: de.comp.datenbanken.*
572 ----- Threshold: 10 => x <= 20 (on average)
573 ----- Grouped by Newsgroups (ascending), sorted by number of postings descending
574
575False by default.
576
577=item B<--comments|--nocomments>
578
579Add comments (group headers) to I<dump> and I<pretty> output. True by default.
580
581Use I<--nocomments> to suppress anything except newsgroup names/months and
582numbers of postings. This is enforced when using B<--filetemplate>, see below.
583
584=item B<--filetemplate> I<filename template>
585
586Save output to file(s) instead of dumping it to STDOUT. B<groupstats> will
587create one file for each month (or each newsgroup, accordant to the
588setting of B<--group-by>, see above), with filenames composed by adding
589year and month (or newsgroup names) to the I<filename template>, for
590example with B<--filetemplate> I<stats>:
591
592 stats-2012-01
593 stats-2012-02
78389b28
TH
594 ... and so on
595
edd250f2 596B<--nocomments> is enforced, see above.
78389b28 597
edd250f2 598=item B<--groupsdb> I<database table>
2832c235
TH
599
600Override I<DBTableGrps> from F<newsstats.conf>.
601
23ab67a0
TH
602=item B<--conffile> I<filename>
603
604Load configuration from I<filename> instead of F<newsstats.conf>.
605
2832c235
TH
606=back
607
608=head1 INSTALLATION
609
edd250f2 610See L<doc/INSTALL>.
2832c235
TH
611
612=head1 EXAMPLES
613
edd250f2 614Show number of postings per group for lasth month in I<pretty> format:
2832c235
TH
615
616 groupstats
617
618Show that report for January of 2010 and de.alt.* plus de.test,
619including display of hierarchy levels:
620
edd250f2 621 groupstats --month 2010-01 --newsgroups de.alt.*:de.test --sums
2832c235 622
edd250f2
TH
623Only show newsgroups with 30 postings or less last month, ordered
624by number of postings, descending, in I<pretty> format:
2832c235 625
edd250f2 626 groupstats --upper 30 --order-by postings-desc
2832c235 627
edd250f2
TH
628Show the total of all postings for the year of 2010 for all groups that
629had 30 postings or less in every single month in that year, ordered by
630number of postings in descending order:
631
632 groupstats -m 2010-01:2010-12 -u 30 -b level -r sums -o postings-desc
2832c235 633
edd250f2 634The same for the average number of postings in the year of 2010:
2832c235 635
edd250f2 636 groupstats -m 2010-01:2010-12 -u 30 -b level -r avg -o postings-desc
2832c235 637
edd250f2
TH
638List number of postings per group for eacht month of 2010 and redirect
639output to one file for each month, namend stats-2010-01 and so on, in
640machine-readable form (without formatting):
2832c235 641
edd250f2 642 groupstats -m 2010-01:2010-12 -f dump --filetemplate stats
2832c235 643
2832c235
TH
644
645=head1 FILES
646
647=over 4
648
2ad99c20 649=item F<bin/groupstats.pl>
2832c235
TH
650
651The script itself.
652
2ad99c20 653=item F<lib/NewsStats.pm>
2832c235
TH
654
655Library functions for the NewsStats package.
656
2ad99c20 657=item F<etc/newsstats.conf>
2832c235 658
edd250f2 659Runtime configuration file.
2832c235
TH
660
661=back
662
663=head1 BUGS
664
665Please report any bugs or feature requests to the author or use the
666bug tracker at L<http://bugs.th-h.de/>!
667
668=head1 SEE ALSO
669
670=over 2
671
672=item -
673
edd250f2 674L<doc/README>
2832c235
TH
675
676=item -
677
edd250f2 678l>doc/INSTALL>
2832c235
TH
679
680=item -
681
682gatherstats -h
683
684=back
685
686This script is part of the B<NewsStats> package.
687
688=head1 AUTHOR
689
690Thomas Hochstein <thh@inter.net>
691
692=head1 COPYRIGHT AND LICENSE
693
edd250f2 694Copyright (c) 2010-2012 Thomas Hochstein <thh@inter.net>
2832c235
TH
695
696This program is free software; you may redistribute it and/or modify it
697under the same terms as Perl itself.
698
699=cut
This page took 0.054262 seconds and 4 git commands to generate.