Newsgroup: it.comp.software.database
Titolo: Una select difficile

(Almeno per me)
vorrei selezionare, da una tabella nella quale sono memorizzate, le date di
creazione dei record,
il numero dei lunedì, dei martedì, mercoledì distinti nei quali è stato
creato almeno un record.
Attenzione: il numero dei giorni _distinti_ non il numero dei record creati
nè dei giorni trascorsi.
Cioè vorrei ad esempio un risultato del tipo:
giorno   |   conteggio
_______________
0            12
1            56
4            2
6            33
dove 0=domenica, 1=lunedì ..... 6=sabato e supponendo quindi che ci siano
state 12 distinte domeniche nelle quali è stato creato almeno 1 record, 56
distinti lunedì, 2 distinti giovedì ecc.
Il giorno della settimana lo ottengo con date_part('dow', timestamp). Ho
provato varie select con distinct, group by ma senza esito. Qualche aiuto?

"Xavier" <nob...@nowhere.invalid> ha scritto nel messaggio
news:aghk9o$19uka$1...@news02.it.net...

Ci provo:
SELECT N_DAY, COUNT(N_COUNT) AS N_COUNT_DAY FROM (SELECT DISTINCT
date_part('dow', timestamp) AS N_DAY, COUNT(REC_ID) AS N_COUNT FROM
MY_TABLE) GROUP BY N_DAY HAVING N_COUNT > 0
E' un po' articolata ma dovrebbe funzionare (credo ;)
Martino

distinti lunedì, 2 distinti giovedì ecc.
SELECT DISTINCT datacreazione FROM tabella;
ti da' tutte le date in cui almeno un record e' stato creato.
SELECT date_part('dow', datacreazione) AS weekday FROM
	(SELECT DISTINCT datacreazione FROM tabella) AS foo
ti converte quelle date in giorni della settimana, ma non fa il
conteggio.
SELECT date_part('dow', datacreazione) AS giorno, COUNT(*) AS conteggio
	FROM (SELECT DISTINCT datacreazione FROM tabella) AS foo
	GROUP BY giorno;
e' la query che cerchi.
Leonardo per approssimazioni successive
-- 
".signature": bad command or file name

 e' la query che cerchi.
Per vari motivi, fin dall'inizio avevo tre colonne per la data: un timestamp
più una date e una time. Così posso usare la tua query sulla colonna date
senza problemi. Però mi piacerebbe sapere perchè diavolo non posso farlo con
il tipo timestamp.
Grazie ancora,
Xavier

 Martino
Grazie, però la risposta di PostgreSQL è:
ERROR:  sub-SELECT in FROM must have an alias
        For example, FROM (SELECT ...) [AS] foo
Se metto un AS foo prima della group by ottengo:
ERROR:  Attribute interventi.apertura must be GROUPed or used in an
aggregate function
dove interventi è la tabella e apertura il campo timestamp.
Vedi anche la risposta che ho dato a Leonardo Serni.
Grazie cmq.
Xavier

"Xavier" <nob...@nowhere.invalid> ha scritto nel messaggio
news:agjg9d$15p6l$1...@news02.it.net...

Infatti dovresti *grouppare* i record per il nome campo sulla query più
esterna (ovvero "select * from (select ...) ")
Probabilmente c'è anche un problema di scope dei campi.
Potresti postare la query (modificata come ti ho suggerito) in modo da darci
un'occhiata?
Martino.

 un'occhiata?
Eccola.
SELECT N_DAY, COUNT(N_COUNT) AS N_COUNT_DAY FROM (SELECT DISTINCT
date_part('dow',richiesto_il) AS N_DAY, COUNT(richiesto_il) AS N_COUNT FROM
interventi) as foo GROUP BY N_DAY HAVING N_COUNT > 0;
ERROR:  Attribute interventi.richiesto_il must be GROUPed or used in an
aggregate function
N.B. In  questo caso ti ho postato la query fatta usando la colonna
richiesto_il che è un tipo date. Perfavore leggi la risposta che ho dato a
Leonardo, dove spiego i problemi che ottengo usare timestamp.
Per inciso, con l'ultima select scritta da Leonardo, e applicata però al
campo date (e non al timestamp, su cui non gira) ottengo il risultato
cercato. In realtà questo è un risultato parziale, perchè quello che voglio
è calcolare la media dei record creati per ogni giorno distinto della
settimana in cui ne è stato creato almeno uno.
ciao, Xavier

"Xavier" <nob...@nowhere.invalid> ha scritto nel messaggio
news:agjhjc$15q3d$1...@news02.it.net...

Mi spiace, per Postgre non sono molto afferrato, l'unica cosa che ti posso
suggerire è di controllare la documentazione su date_part()

il tipo timestamp.
Questo in effetti e' buffo. Indagheroe.
create table test ( tempus timestamp );
CREATE
insert into test values (now());
INSERT 27455131 1
insert into test values (now());
INSERT 27455134 1
insert into test values (now());
INSERT 27455135 1
insert into test values (now());
INSERT 27455136 1
select date_part('dow', tempus) from test;
 date_part
-----------
         4
         4
         4
         4
(4 rows)
select version();
                            version
---------------------------------------------------------------
 PostgreSQL 7.2.1 (20020627.0018), GCC 2.95.3 (/etc/sinfo.txt)
(1 row)
--------
Puoi postare lo schema (pg_dump -sint nometabella database)?
Leonardo perplesso


 Puoi postare lo schema (pg_dump -sint nometabella database)?
Eccolo qui di seguito.
Cmq, se il problema di fare la select con un timestamp è irresolubile, la
farò con il date, poco male.
Il fatto è che il risultato finale non è ancora raggiunto. Quello che voglio
fare, con l'output di questa select, è calcolare la media record creati /
giorni distinti. In sintesi, e ad esempio, vorrei un output del tipo:
(dove conteggio è il risultato della select di cui sopra)
giorno  |   record_creati_in_tutto   |   conteggio  |  media_ per_
giorno_conteggiato
----------------------------------------------------------------------------
------
lun       |               1200                |        8          |
150
mar     |                2500                |        8         |
312,5
mer     |                3600                |        7          |
514,3
gio       |               1800                |        8          |
225
ven       |               1600                |        8          |
200
sab       |                   20                |        2          |
10
In questo esempio ho supposto che ci sia stato un mercoledì non lavorativo e
due sabati lavorativi. La tabella registra gli interventi di assistenza
effettuati. Nel calcolo dei record medi non voglio contare i giorni non
lavorati, non avrebbe senso. Ovviamente tutto questo discorso va bene se in
ogni giorno lavorativo viene creato almeno un record, ma questo è il caso.
saluti,
Xavier
--
-- Selected TOC Entries:
--
\connect - helpdesk
--
-- TOC Entry ID 2 (OID 5600365)
--
-- Name: interventi_id_seq Type: SEQUENCE Owner: helpdesk
--
CREATE SEQUENCE interventi_id_seq start 1 increment 1 maxvalue 
2147483647
minvalue 1  cache 1 ;
--
-- TOC Entry ID 3 (OID 5600384)
--
-- Name: interventi Type: TABLE Owner: helpdesk
--
CREATE TABLE interventi (
 id integer DEFAULT nextval('"interventi_id_seq"'::text) NOT NULL,
 richiesto_il date DEFAULT date('now'::text),
 richiesto_da integer NOT NULL,
 area_interv integer DEFAULT 0 NOT NULL,
 soggetto character varying(30) NOT NULL,
 descr text,
 stato_id integer DEFAULT 0,
 esaminato_da integer,
 esaminato_il date,
 info_aggiunt text,
 priorita_id integer DEFAULT 1,
 assegnato_a integer,
 assegnato_il date,
 chiuso_il date,
 soluzione text,
 allegato1 text,
 allegato2 text,
 allegato3 text,
 allegato4 text,
 richiesto_ora time DEFAULT now(),
 ult_modif_il date DEFAULT now(),
 ult_modif_ora time DEFAULT now(),
 cod_az integer,
 codiceintervento integer,
 apertura timestamp with time zone DEFAULT now(),
 chiusura timestamp with time zone,
 tempodichiusura interval
);
--
-- TOC Entry ID 4 (OID 5600384)
--
-- Name: interventi_id_key Type: INDEX Owner: helpdesk
--
CREATE UNIQUE INDEX interventi_id_key on interventi using btree ( id
int4_ops );
--
-- TOC Entry ID 5 (OID 5600648)
--
-- Name: "RI_ConstraintTrigger_5600647" Type: TRIGGER Owner: helpdesk
--
CREATE CONSTRAINT TRIGGER "<unnamed>" AFTER INSERT OR UPDATE ON interventi
FROM aree_interv NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE "RI_FKey_check_ins" ('<unnamed>', 'interventi', 'aree_interv',
'UNSPECIFIED', 'area_interv', 'id');
--
-- TOC Entry ID 6 (OID 5600654)
--
-- Name: "RI_ConstraintTrigger_5600653" Type: TRIGGER Owner: helpdesk
--
CREATE CONSTRAINT TRIGGER "<unnamed>" AFTER INSERT OR UPDATE ON interventi
FROM utenti NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE "RI_FKey_check_ins" ('<unnamed>', 'interventi', 'utenti',
'UNSPECIFIED', 'richiesto_da', 'id');
--
-- TOC Entry ID 7 (OID 5600660)
--
-- Name: "RI_ConstraintTrigger_5600659" Type: TRIGGER Owner: helpdesk
--
CREATE CONSTRAINT TRIGGER "<unnamed>" AFTER INSERT OR UPDATE ON interventi
FROM utenti NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE "RI_FKey_check_ins" ('<unnamed>', 'interventi', 'utenti',
'UNSPECIFIED', 'esaminato_da', 'id');
--
-- TOC Entry ID 8 (OID 5600666)
--
-- Name: "RI_ConstraintTrigger_5600665" Type: TRIGGER Owner: helpdesk
--
CREATE CONSTRAINT TRIGGER "<unnamed>" AFTER INSERT OR UPDATE ON interventi
FROM priorita NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE "RI_FKey_check_ins" ('<unnamed>', 'interventi', 'priorita',
'UNSPECIFIED', 'priorita_id', 'id');
--
-- TOC Entry ID 9 (OID 5600672)
--
-- Name: "RI_ConstraintTrigger_5600671" Type: TRIGGER Owner: helpdesk
--
CREATE CONSTRAINT TRIGGER "<unnamed>" AFTER INSERT OR UPDATE ON interventi
FROM utenti NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE "RI_FKey_check_ins" ('<unnamed>', 'interventi', 'utenti',
'UNSPECIFIED', 'assegnato_a', 'id');
--
-- TOC Entry ID 10 (OID 5600678)
--
-- Name: "RI_ConstraintTrigger_5600677" Type: TRIGGER Owner: helpdesk
--
CREATE CONSTRAINT TRIGGER "<unnamed>" AFTER INSERT OR UPDATE ON interventi
FROM stati NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE
"RI_FKey_check_ins" ('<unnamed>', 'interventi', 'stati', 'UNSPECIFIED',
'stato_id', 'id');
--
-- TOC Entry ID 11 (OID 7002878)
--
-- Name: trigger_aggiorna_data_ora Type: TRIGGER Owner: helpdesk
--
CREATE TRIGGER trigger_aggiorna_data_ora BEFORE UPDATE ON interventi  FOR
EACH ROW EXECUTE PROCEDURE aggiorna_data_ora ();
--
-- TOC Entry ID 12 (OID 7002880)
--
-- Name: trigger_memo_chiusura_e_calcolo Type: TRIGGER Owner: helpdesk
--
CREATE TRIGGER trigger_memo_chiusura_e_calcolo BEFORE UPDATE ON interventi
FOR EACH ROW EXECUTE PROCEDURE memo_chiusura_e_calcolo ();

giorno_conteggiato
Ohhhh... allora la mia prima query faceva un'altra cosa.
Inserisco un altro po' di duplicati. Ci sono 12 date distinte con un totale
di 119 interventi.
select apertura::date as datapert, count(*) from interventi group by
datapert;
  datapert  | count
------------+-------
 2002-07-01 |     2
 2002-07-02 |     2
 2002-07-03 |     2
 2002-07-04 |     1
 2002-07-05 |     1
 2002-07-10 |     1
 2002-07-11 |    28
 2002-07-12 |    38
 2002-07-13 |    17
 2002-07-14 |     9
 2002-07-15 |     9
 2002-07-20 |     9
select date_part('dow', datapert) AS giorno, count(*) AS giorni,
sum(interv) AS interventi FROM ( SELECT apertura::date as datapert,
count(*) as interv from interventi group by datapert ) as foo group by
giorno;
 giorno | giorni | interventi
--------+--------+------------
      0 |      1 |          9
      1 |      2 |         11
      2 |      1 |          2
      3 |      2 |          3
      4 |      2 |         29
      5 |      2 |         39
      6 |      2 |         26
SELECT
    SUBSTR('DomLunMarMerGioVenSab', 1+3*giorno, 3)
        AS "giorno della settimana",
    giorni, interventi, media
    FROM 
    ( SELECT date_part('dow', datapert) AS giorno, 
        count(*) AS giorni, sum(interv) AS interventi,
        CASE 
            WHEN count(*) = 0 THEN 0 
            ELSE sum(interv)::float8/count(*)::float8
        END AS media
        FROM 
        (
            SELECT apertura::date as datapert, count(*) AS interv
                FROM interventi GROUP BY datapert ) AS foo
            GROUP BY giorno ) AS bar
ORDER BY (giorno::integer+6)%7;
-- Un altro catafrastico trucco del palingenetico Mago Afono
 giorno della settimana | giorni | interventi | media
------------------------+--------+------------+-------
 Lun                    |      2 |         11 |   5.5
 Mar                    |      1 |          2 |     2
 Mer                    |      2 |          3 |   1.5
 Gio                    |      2 |         29 |  14.5
 Ven                    |      2 |         39 |  19.5
 Sab                    |      2 |         26 |    13
 Dom                    |      1 |          9 |     9
Leonardo


         AS "giorno della settimana",
[cut]
Il tempo di capirla  (spero) e applicarla, ti rispondo domani.
In ogni caso sei un mito.
Saluti & grazie,
Xavier

esterna?
Si', perche' se fai
	SELECT DISTINCT datacreazione
allora quel campo li' si chiama datacreazione, e puoi usarlo:
	SELECT datacreazione FROM (SELECT datacreazione FROM ...
Ma se fai
	SELECT date_part('dow', datacreazione)
quel campo si chiama "date_part", a meno che tu non gli cambi nome usando
un AS, e se faccio
	SELECT datacreazione FROM (SELECT date_part(...
PostgreSQL giustamente (secondo lui) mi dice cosacce sulla mi' mamma :-)
Quanto alla query che ti avevo postato, funziona perfettamente (7.2.1): a
meno che tu non ne abbia invece usata una che era solo... "simile" :-)


 SELECT datacreazione FROM (SELECT datacreazione FROM ...
Appunto, non capisco. Nella tua prima select:
SELECT date_part('dow', datacreazione) AS giorno, COUNT(*) AS conteggio
FROM (SELECT DISTINCT datacreazione FROM tabella) AS foo
GROUP BY giorno;
la select piů interna prende il nome di datacreazione e con quel nome viene
usata dalla date_part della select esterna.
Perchč con apertura::date al posto di datacreazione non funzionava e invece
con richiesto_il (tipo date) sě???
Per il resto la tua superselect funziona benissimo, solo che per avere il
nome dei giorni per esteso ho dovuto aggiungere nel php un pň di codice:
switch ($fldgiornosett) {
   case 'Dom': $fldgiornosett = 'Domenica'; break;
   case 'Lun': $fldgiornosett = 'Lunedě'; break;
   case 'Mar': $fldgiornosett = 'Martedě'; break;
   case 'Mer': $fldgiornosett = 'Mercoledě'; break;
   case 'Gio': $fldgiornosett = 'Giovedě'; break;
   case 'Ven': $fldgiornosett = 'Venerdě'; break;
   case 'Sab': $fldgiornosett = 'Sabato'; break;
}
THX e6
Xavier

nome dei giorni per esteso ho dovuto aggiungere nel php un pň di codice:
Se usi PHP ti conviene far cosi': NON usare substr(...) nella superselect
e lascia invece "dow", numero da 0 a 6. Poi in PHP metti
	$giornosett = array( 0 => 'Domenica', ... );
	$fldgiornosett = $giornosett[$fldgiornosett];
cosi' ti risparmi lo switch.
