Pregunta

Tengo una tabla llamada OffDays, donde los fines de semana y feriados se mantienen.Tengo una tabla llamada plazo de obtención de donde la cantidad de tiempo (en días) para que un producto sea fabricado se almacena.Finalmente tengo una tabla llamada Orden donde un producto y la fecha de la orden se mantiene.

Es posible la consulta cuando un producto terminado de fabricación sin necesidad de utilizar procedimientos almacenados o bucles?

Por ejemplo:

  • OffDays ha 2008-01-10, 2008-01-11, 2008-01-14.
  • Plazo de obtención de la haya de 5 de producto 9.
  • La orden ha 2008-01-09 de producto 9.

El cálculo estoy buscando es esto:

  • 2008-01-09 1
  • 2008-01-10 x
  • 2008-01-11 x
  • 2008-01-12 2
  • 2008-01-13 3
  • 2008-01-14 x
  • 2008-01-15 4
  • 2008-01-16 5

Me pregunto si es posible tener una consulta de retorno 2008-01-16 sin tener que utilizar un procedimiento almacenado, o el cálculo en mi código de la aplicación.

Editar (¿por qué no almacena los procs / loops): La razón por la que no puede utilizar los procedimientos almacenados es que ellos no son compatibles con la base de datos.Sólo puedo añadir extra de tablas de datos.La aplicación es una tercera parte de la herramienta de informes donde puedo sólo de control de la consulta SQL.

Editar (¿cómo lo estoy haciendo ahora): Mi método actual es que tengo una columna adicional en la tabla de pedidos para celebrar la fecha calculada, entonces una tarea programada / cron que se ejecuta el trabajo el cálculo en todos los órdenes de cada hora.Esto es menos que ideal por varias razones.

¿Fue útil?

Solución

Usted puede generar una mesa de trabajo días de antelación.

WDId | WDDate
-----+-----------
4200 | 2008-01-08
4201 | 2008-01-09
4202 | 2008-01-12
4203 | 2008-01-13
4204 | 2008-01-16
4205 | 2008-01-17

A continuación, hacer una consulta, tales como

SELECT DeliveryDay.WDDate FROM WorkingDay OrderDay, WorkingDay DeliveryDay, LeadTime, Order where DeliveryDay.WDId = OrderDay.WDId + LeadTime.LTDays AND OrderDay.WDDate = '' AND LeadTime.ProductId = Order.ProductId AND Order.OrderId = 1234

Usted necesita un procedimiento almacenado con un bucle para generar el WorkingDays de mesa, pero no para consultas regulares.Es también un menor número de viajes de ida y vuelta al servidor que si usas el código de la aplicación para contar los días.

Otros consejos

El mejor enfoque es el uso de un Calendario de mesa.

Ver http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html.

A continuación, la consulta podría ser algo como:

SELECT c.dt, l.*, o.*, c.*
    FROM [statistics].dbo.[calendar] c, 
    [order] o  JOIN
    lead l ON l.leadId = o.leadId
    WHERE c.isWeekday = 1 
    AND   c.isHoliday =0 
    AND   o.orderId = 1
    AND   l.leadDays = ( 
        SELECT COUNT(*)  
            FROM [statistics].dbo.Calendar c2 
            WHERE c2.dt >= o.startDate
            AND c2.dt <= c.dt 
            AND c2.isWeekday=1 
            AND c2.isHoliday=0 
    )

Espero que ayude,

RB.

Solo calcularlo en el código de la aplicación ...mucho más fácil y usted no tendrá que escribir una muy feo consulta en sql

he aquí una manera - mediante la función dateadd.

Necesito tomar esta respuesta fuera de la mesa.Esto no va a funcionar correctamente para largos tiempos de entrega.Era simplemente agregando el # de días de descanso se encuentra en el tiempo de entrega y empujando la fecha de salida.Esto causará un problema cuando más los días de descanso se muestran en la nueva gama.

-- Setup test
create table #odays (offd datetime)
create table #leadtime (pid int , ltime int)
create table [#order] (pid int, odate datetime)


insert into #odays 
select '1/10/8'
insert into #odays 
select '1/11/8'
insert into #odays 
select '1/14/8'


insert into #Leadtime
values (3,5)
insert into #leadtime
values (9, 5)

insert into #order 
values( 9, '1/9/8')

select dateadd(dd, 
(select count(*)-1 
   from #odays 
   where offd between odate and  
    (select odate+ltime 
       from #order o 
       left join #leadtime l 
         on o.pid = l.pid 
       where l.pid = 9
     )
 ),
 odate+ltime) 
 from #order o 
 left join #leadtime l  
   on o.pid = l.pid 
 where o.pid = 9

Por qué están en contra de la utilización de bucles?

//algunos pseudocódigo

int leadtime = 5;
date order = 2008-01-09;
date finishdate = order;
while (leadtime > 0) {
finishdate.addDay();
if (!IsOffday(finishdate)) leadtime--;
}
return finishdate;

esto parece demasiado simple función para tratar de encontrar una no-forma de bucle.

Hmm..una solución podría ser la de almacenar una tabla de fechas con un desplazamiento basado en el número de no-fuera de los días desde el comienzo del año.Digamos, por ejemplo, jan.2 es un día de descanso.1/1/08 habría un desplazamiento de 1 (o 0 si te gustaría empezar de 0).1/3/08 habría un desplazamiento de 2, debido a que el recuento de salta 1/2/08.A partir de allí un cálculo simple.Obtener el desplazamiento de la fecha de pedido, añadir el tiempo de entrega, a continuación, hacer una búsqueda en el cálculo del desplazamiento para obtener la fecha de finalización.

Una manera (sin necesidad de crear otra tabla) es el uso de una especie de techo de la función:para cada offdate, averiguar cuántos "en las fechas" vendrá delante de ella, en relación a la fecha de la orden, en una subconsulta.A continuación, tomar el mayor número que es menor que el tiempo de entrega.El uso de la fecha correspondiente para que, además de el resto.

Este código puede ser específico para PostgreSQL, lo siento si eso no es lo que se está utilizando.

CREATE DATABASE test;
CREATE TABLE offdays
(
  offdate date NOT NULL,
  CONSTRAINT offdays_pkey PRIMARY KEY (offdate)
);
insert into offdays (offdate) values ('2008-01-10');
insert into offdays (offdate) values ('2008-01-11');
insert into offdays (offdate) values ('2008-01-14');
insert into offdays (offdate) values ('2008-01-18'); -- just for testing
CREATE TABLE product
(
  id integer NOT NULL,
  CONSTRAINT product_pkey PRIMARY KEY (id)
);
insert into product (id) values (9);
CREATE TABLE leadtime
(
  product integer NOT NULL,
  leaddays integer NOT NULL,
  CONSTRAINT leadtime_pkey PRIMARY KEY (product),
  CONSTRAINT leadtime_product_fkey FOREIGN KEY (product)
      REFERENCES product (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);
insert into leadtime (product, leaddays) values (9, 5);
CREATE TABLE "order"
(
  product integer NOT NULL,
  "start" date NOT NULL,
  CONSTRAINT order_pkey PRIMARY KEY (product),
  CONSTRAINT order_product_fkey FOREIGN KEY (product)
      REFERENCES product (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);
insert into "order" (product, "start") values (9, '2008-01-09');

-- finally, the query:

select e.product, offdate + (leaddays - ondays)::integer as "end"
from
(
    select c.product, offdate, (select (a.offdate - c."start") - count(b.offdate) from offdays b where b.offdate < a.offdate) as ondays, d.leaddays
    from offdays a, "order" c
    inner join leadtime d on d.product = c.product
) e
where leaddays >= ondays
order by "end" desc
limit 1;

Este es PostgreSQL sintaxis pero debe ser fácil de traducir a otros dialecto SQL

--Sample data
create table offdays(datum date);

insert into offdays(datum)
select to_date('2008-01-10','yyyy-MM-dd') UNION 
select to_date('2008-01-11','yyyy-MM-dd') UNION 
select to_date('2008-01-14','yyyy-MM-dd') UNION 
select to_date('2008-01-20','yyyy-MM-dd') UNION
select to_date('2008-01-21','yyyy-MM-dd') UNION
select to_date('2008-01-26','yyyy-MM-dd');

create table leadtime (product_id integer , lead_time integer);
insert into leadtime(product_id,lead_time) values (9,5);

create table myorder (order_id integer,product_id integer, datum date);
insert into myorder(order_id,product_id,datum) 
values (1,9,to_date('2008-01-09','yyyy-MM-dd'));
insert into myorder(order_id,product_id,datum) 
values (2,9,to_date('2008-01-16','yyyy-MM-dd'));
insert into myorder(order_id,product_id,datum) 
values (3,9,to_date('2008-01-23','yyyy-MM-dd'));

--Query
select order_id,min(finished_date)
FROM 
    (select mo.order_id,(mo.datum+lead_time+count(od2.*)::integer-1) as finished_date
     from 
         myorder mo
         join leadtime lt on (mo.product_id=lt.product_id)
         join offdays od1 on (mo.datum<od1.datum)
         left outer join offdays od2 on (mo.datum<od2.datum and od2.datum<od1.datum)
     group by  mo.order_id,mo.datum,lt.lead_time,od1.datum
     having (mo.datum+lead_time+count(od2.*)::integer-1) < od1.datum) tmp
group by 1;       

--Results :
1    2008.01.16
2    2008.01.22

Esto no volver resultado para los pedidos que se terminó después de la última fecha en offdays tabla (número de pedido 3), por lo que se debe tener cuidado para insertar offdays en el tiempo.Se supone que las órdenes no se inician en offdays.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top