2011-02-17 25 views

Respuesta

4

El número total de los domingos para una fecha determinada sólo puede ser 0 o 1.

Pero si desea que el número de domingos dentro de un intervalo de tiempo dado, entonces su mejor apuesta es una tabla de calendario . Para saber cuántos domingos son en febrero de este año, que acababa de

select count(*) 
from calendar 
where cal_date between '2011-02-01' and '2011-02-28' and 
     day_of_week = 'Sun'; 

o

select count(*) 
from calendar 
where year_of_date = 2011 and 
     month_of_year = 2 and 
     day_of_week = 'Sun'; 

Aquí hay una tabla de calendario básico que se puede empezar. También incluí una función PostgreSQL para poblar la tabla de calendario. No he probado esto en 8.3, pero estoy bastante seguro de que no estoy usando ninguna característica que 8.3 no sea compatible.

Tenga en cuenta que las partes "dow" asumen que sus días están en inglés. Pero puede editar fácilmente esas partes para que coincidan con cualquier idioma. (Creo. Pero podría estar equivocado acerca de "fácil".)

-- Table: calendar 

-- DROP TABLE calendar; 

CREATE TABLE calendar 
(
    cal_date date NOT NULL, 
    year_of_date integer NOT NULL, 
    month_of_year integer NOT NULL, 
    day_of_month integer NOT NULL, 
    day_of_week character(3) NOT NULL, 
    CONSTRAINT calendar_pkey PRIMARY KEY (cal_date), 
    CONSTRAINT calendar_check CHECK (year_of_date::double precision = date_part('year'::text, cal_date)), 
    CONSTRAINT calendar_check1 CHECK (month_of_year::double precision = date_part('month'::text, cal_date)), 
    CONSTRAINT calendar_check2 CHECK (day_of_month::double precision = date_part('day'::text, cal_date)), 
    CONSTRAINT calendar_check3 CHECK (day_of_week::text = 
CASE 
    WHEN date_part('dow'::text, cal_date) = 0::double precision THEN 'Sun'::text 
    WHEN date_part('dow'::text, cal_date) = 1::double precision THEN 'Mon'::text 
    WHEN date_part('dow'::text, cal_date) = 2::double precision THEN 'Tue'::text 
    WHEN date_part('dow'::text, cal_date) = 3::double precision THEN 'Wed'::text 
    WHEN date_part('dow'::text, cal_date) = 4::double precision THEN 'Thu'::text 
    WHEN date_part('dow'::text, cal_date) = 5::double precision THEN 'Fri'::text 
    WHEN date_part('dow'::text, cal_date) = 6::double precision THEN 'Sat'::text 
    ELSE NULL::text 
END) 
) 
WITH (
    OIDS=FALSE 
); 
ALTER TABLE calendar OWNER TO postgres; 

-- Index: calendar_day_of_month 

-- DROP INDEX calendar_day_of_month; 

CREATE INDEX calendar_day_of_month 
    ON calendar 
    USING btree 
    (day_of_month); 

-- Index: calendar_day_of_week 

-- DROP INDEX calendar_day_of_week; 

CREATE INDEX calendar_day_of_week 
    ON calendar 
    USING btree 
    (day_of_week); 

-- Index: calendar_month_of_year 

-- DROP INDEX calendar_month_of_year; 

CREATE INDEX calendar_month_of_year 
    ON calendar 
    USING btree 
    (month_of_year); 

-- Index: calendar_year_of_date 

-- DROP INDEX calendar_year_of_date; 

CREATE INDEX calendar_year_of_date 
    ON calendar 
    USING btree 
    (year_of_date); 

y una función rudimentaria para rellenar la tabla. Tampoco he probado esto en 8.3.

-- Function: insert_range_into_calendar(date, date) 

-- DROP FUNCTION insert_range_into_calendar(date, date); 

CREATE OR REPLACE FUNCTION insert_range_into_calendar(from_date date, to_date date) 
    RETURNS void AS 
$BODY$ 

DECLARE 
    this_date date := from_date; 
BEGIN 

    while (this_date <= to_date) LOOP 
     INSERT INTO calendar (cal_date, year_of_date, month_of_year, day_of_month, day_of_week) 
     VALUES (this_date, extract(year from this_date), extract(month from this_date), extract(day from this_date), 
     case when extract(dow from this_date) = 0 then 'Sun' 
      when extract(dow from this_date) = 1 then 'Mon' 
      when extract(dow from this_date) = 2 then 'Tue' 
      when extract(dow from this_date) = 3 then 'Wed' 
      when extract(dow from this_date) = 4 then 'Thu' 
      when extract(dow from this_date) = 5 then 'Fri' 
      when extract(dow from this_date) = 6 then 'Sat' 
     end); 
     this_date = this_date + interval '1 day'; 
    end loop;  

END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
+0

calendario de la tabla es una tabla predeterminada o tenemos que crear? – ungalnanban

+0

Estoy usando PostgreSQL 8.3. No tengo la tabla de calendario – ungalnanban

+0

Use generate_series, vea mi respuesta. –

8

Es necesario EXTRACTO:

SELECT 
    EXTRACT(DOW FROM DATE '2011-02-16') = 0; -- 0 is Sunday 

Esto puede dar como resultado verdadero o falso, es un domingo o no lo es. No tengo idea de a qué te refieres con "número total" porque siempre será 0 (la fecha no es un domingo) o 1 (la información dada es un domingo).

Editar: ¿Algo como esto?

SELECT 
    COUNT(*) 
FROM 
    generate_series(timestamp '2011-01-01', '2011-03-01', '1 day') AS g(mydate) 
WHERE 
    EXTRACT(DOW FROM mydate) = 0; 
+0

Su pregunta es "¿Cómo obtener el conteo del mes actual del domingo en psql?" Entonces debe hacer un recuento() en el rango – stefan

+0

@Catcall cité la pregunta (vea el título) sobre la descripción, supongo que la "fecha dada" es la fecha del mes. Pero sí, es fácil perder :) – stefan

+0

También podría usar SUM() por cierto, (creo, ehrm) ;-) – stefan

Cuestiones relacionadas