Cómo obtener este resultado (actualizar la fecha según el registro que sigue)

13/03/2009 - 12:34 por DT | Informe spam
Hola
Tengo dos tablas, T1 y T2. T1 Tiene los campos de Fecha y Valor, fecha
corresponde a una lista de fechas que puede ser un mes entero, un año entero
(en orden), Valor es un campo vacío que debe tener los valores de T2.

Tengo una tabla con este contenido:
ID Fecha Valor
BN 01/01/2009 NULL
BN 01/02/2009 NULL
BN 01/03/2009 NULL
BN 01/04/2009 NULL
...

La T2 tiene los siguientes campos:
ID Fecha_Inicio PRECIO
BN 12/01/2008 100
BN 01/03/2009 105
BN 01/04/2009 200

Tengo que tener este resultado en T1
ID Fecha Valor
BN 01/01/2009 100
BN 01/02/2009 100
BN 01/03/2009 105
BN 01/04/2009 200

El pseudocódigo sería:
Actualizar T1 - Poner en VALOR
(
El PRECIO desde la Fecha de INICIO hasta la FECHA de Cada producto)

Sabiendo que la fecha de inicio siguiente -1 es la fecha en que termina el
producto (campo no existe)

1000 gracias, espero haber sido claro... :_)

Preguntas similare

Leer las respuestas

#1 Carlos Sacristan
13/03/2009 - 12:54 | Informe spam
Para una posible solución te vendría bien una tabla de números. La idea
sería hacer el JOIN entre T1 y T2 por el ID, y por otro lado hacer un JOIN
entre el resultado de calcular el nº de días entre la fecha y la Fecha_inicio
y el número de la tabla en cuestión. Algo como...

SELECT t1.ID, DATEADD(d, n.numero, fecha_inicio), t1.valor
FROM T1 INNER JOIN T2 ON T1.ID=T2.ID
INNER JOIN t_numeros n ON n.numero BETWEEN 0 AND DATEDIFF(d,
fecha_inicio, fecha)

No lo he probado y está pensado deprisa y corriendo, pero por ahí va la idea.
Un saludo
-
www.navento.com
Servicios de Localización GPS


"DT" wrote:

Hola
Tengo dos tablas, T1 y T2. T1 Tiene los campos de Fecha y Valor, fecha
corresponde a una lista de fechas que puede ser un mes entero, un ao entero
(en orden), Valor es un campo vaco que debe tener los valores de T2.

Tengo una tabla con este contenido:
ID Fecha Valor
BN 01/01/2009 NULL
BN 01/02/2009 NULL
BN 01/03/2009 NULL
BN 01/04/2009 NULL
...

La T2 tiene los siguientes campos:
ID Fecha_Inicio PRECIO
BN 12/01/2008 100
BN 01/03/2009 105
BN 01/04/2009 200

Tengo que tener este resultado en T1
ID Fecha Valor
BN 01/01/2009 100
BN 01/02/2009 100
BN 01/03/2009 105
BN 01/04/2009 200

El pseudocdigo sera:
Actualizar T1 - Poner en VALOR
(
El PRECIO desde la Fecha de INICIO hasta la FECHA de Cada producto)

Sabiendo que la fecha de inicio siguiente -1 es la fecha en que termina el
producto (campo no existe)

1000 gracias, espero haber sido claro... :_)

Respuesta Responder a este mensaje
#2 Alejandro Mesa
13/03/2009 - 14:11 | Informe spam
DT,

Cual es la version de SQL Server que usas?

Aqui expongo dos posibles soluciones. La primera usa un subquery
correlacionado para encontrar la fecha final de cada fila en T2. La segunda
usa la funcion row_number() para encontrar la fecha fin.

Si por casualidad usas una version de SQL Server menor a 2005, entonces
tendras que lidear con la primera propuesta, solo debes usar la sentencia que
define la CTE como una tabla derivada.


;WITH fechaRango
AS
(
SELECT
a.ID,
a.Fecha_Inicio,
ISNULL(
(
SELECT
DATEADD([day], -1, MIN(b.Fecha_Inicio))
FROM
T2 AS b
WHERE
b.[ID] = a.[ID]
AND b.Fecha_Inicio > a.Fecha_Inicio
AND b.Precio <> a.Precio
), Fecha_Inicio) AS Fecha_Fin,
a.Precio
FROM
T2 AS a
)
UPDATE
a
SET
a.Precio = fr.Precio
FROM
T1 AS a
INNER JOIN
FechaRango AS fr
ON a.ID = fr.ID
AND a.Fecha_Inicio BETWEEN fr.Fecha_Inicio AND Fecha_Fin;
GO

Deja ver si explico la idea sin confundir al lector. Para cada fila en T2,
haya la minima fecha de inicio de las filas que tienen igual ID a la fila que
se procesa, cuyo valor de la columna precio es diferente al precio de la fila
que procesamos. Le restamos un dia a dicha fecha y obtenemos la fecha fin de
esa fila. Si la fila es la ultima en su grupo, entonces usamos su propia
fecha de inicio como la fecha fin.

Basado en tu data de ejemplo (hombre un esfuerzito para poner un par mas de
filas, al menos un par mas de IDs), tendriamos:

ID Fecha_Inicio Fecha_Fin Precio
BN 12/01/2008 01/02/2009 100
BN 01/03/2009 01/03/2009 105
BN 01/04/2009 01/04/2009 200

Ahora solo basta unir la tabla T1 con este resultado, usando el operador
BETWEEN.

Casi siempre, los subqueries correlacionados tienden a disminuir el
desempenio de un query, sobre todo si el numero de filas para el cual debemos
ejecutar el subquery aumenta. Asi que expongo otra posible solucion, que usa
la funcion row_number para asignar un # a cada fila, particionando las filas
por ID y ordenandolas por la fecha de inicio. Basado en tu data de ejemplo
tendriamos un resultado intermedio como:

ID Fecha_Inicio Precio rn
BN 12/01/2008 100 1
BN 01/03/2009 105 2
BN 01/04/2009 200 3

Ahora, si unimos (join) este resultado intermedio consigo mismo, mediante la
expresion a.ID = b.ID and a.rn = b.rn - 1, estariamos uniendo

BN(1) - BN(2)
BN(2) - BN(3)

y por tanto, la fecha final de cada fila en el lado izquierdo (llamemosle
"a"), seria la fecha de inicio de el lado "b" menos un dia. Aqui hacemos lo
mismo para las filas que son la ultima en su grupo, le asignamos como fecha
final su propia fecha de inicio. Ejemplo:

ID Fecha_Inicio Fecha_Fin Precio
BN 01/04/2009 01/04/2009 200

;WITH r_set
AS
(
ID,
Fecha_Inicio,
Precio,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Fecha_Inicio) AS rn
FROM
T2
),
FechaRango
AS
(
SELECT
a.ID,
a.Fecha_Inicio,
ISNULL(DATEADD([day], -1, b.Fecha_Inicio), a.Fecha_Inicio) AS Fecha_Fin,
a.Precio
FROM
r_set AS a
LEFT OUTER JOIN
r_Set AS b
ON a.ID = b.ID
AND a.rn = b.rn - 1
)
UPDATE
a
SET
a.Precio = fr.Precio
FROM
T1 AS a
INNER JOIN
FechaRango AS fr
ON a.ID = fr.ID
AND a.Fecha_Inicio BETWEEN fr.Fecha_Inicio AND Fecha_Fin;
GO

Debido a la complejidad de solucion que usa la funcion row_number,
posiblemente su desempenio este a la par de la solucion que usa query
correlacionado, si el # de filas no es mucho.


AMB


"DT" wrote:

Hola
Tengo dos tablas, T1 y T2. T1 Tiene los campos de Fecha y Valor, fecha
corresponde a una lista de fechas que puede ser un mes entero, un ao entero
(en orden), Valor es un campo vaco que debe tener los valores de T2.

Tengo una tabla con este contenido:
ID Fecha Valor
BN 01/01/2009 NULL
BN 01/02/2009 NULL
BN 01/03/2009 NULL
BN 01/04/2009 NULL
...

La T2 tiene los siguientes campos:
ID Fecha_Inicio PRECIO
BN 12/01/2008 100
BN 01/03/2009 105
BN 01/04/2009 200

Tengo que tener este resultado en T1
ID Fecha Valor
BN 01/01/2009 100
BN 01/02/2009 100
BN 01/03/2009 105
BN 01/04/2009 200

El pseudocdigo sera:
Actualizar T1 - Poner en VALOR
(
El PRECIO desde la Fecha de INICIO hasta la FECHA de Cada producto)

Sabiendo que la fecha de inicio siguiente -1 es la fecha en que termina el
producto (campo no existe)

1000 gracias, espero haber sido claro... :_)

Respuesta Responder a este mensaje
#3 DT
13/03/2009 - 21:27 | Informe spam
muchas gracias, maestro!

"Alejandro Mesa" wrote in message
news:
DT,

Cual es la version de SQL Server que usas?

Aqui expongo dos posibles soluciones. La primera usa un subquery
correlacionado para encontrar la fecha final de cada fila en T2. La
segunda
usa la funcion row_number() para encontrar la fecha fin.

Si por casualidad usas una version de SQL Server menor a 2005, entonces
tendras que lidear con la primera propuesta, solo debes usar la sentencia
que
define la CTE como una tabla derivada.


;WITH fechaRango
AS
(
SELECT
a.ID,
a.Fecha_Inicio,
ISNULL(
(
SELECT
DATEADD([day], -1, MIN(b.Fecha_Inicio))
FROM
T2 AS b
WHERE
b.[ID] = a.[ID]
AND b.Fecha_Inicio > a.Fecha_Inicio
AND b.Precio <> a.Precio
), Fecha_Inicio) AS Fecha_Fin,
a.Precio
FROM
T2 AS a
)
UPDATE
a
SET
a.Precio = fr.Precio
FROM
T1 AS a
INNER JOIN
FechaRango AS fr
ON a.ID = fr.ID
AND a.Fecha_Inicio BETWEEN fr.Fecha_Inicio AND Fecha_Fin;
GO

Deja ver si explico la idea sin confundir al lector. Para cada fila en T2,
haya la minima fecha de inicio de las filas que tienen igual ID a la fila
que
se procesa, cuyo valor de la columna precio es diferente al precio de la
fila
que procesamos. Le restamos un dia a dicha fecha y obtenemos la fecha fin
de
esa fila. Si la fila es la ultima en su grupo, entonces usamos su propia
fecha de inicio como la fecha fin.

Basado en tu data de ejemplo (hombre un esfuerzito para poner un par mas
de
filas, al menos un par mas de IDs), tendriamos:

ID Fecha_Inicio Fecha_Fin Precio
BN 12/01/2008 01/02/2009 100
BN 01/03/2009 01/03/2009 105
BN 01/04/2009 01/04/2009 200

Ahora solo basta unir la tabla T1 con este resultado, usando el operador
BETWEEN.

Casi siempre, los subqueries correlacionados tienden a disminuir el
desempenio de un query, sobre todo si el numero de filas para el cual
debemos
ejecutar el subquery aumenta. Asi que expongo otra posible solucion, que
usa
la funcion row_number para asignar un # a cada fila, particionando las
filas
por ID y ordenandolas por la fecha de inicio. Basado en tu data de ejemplo
tendriamos un resultado intermedio como:

ID Fecha_Inicio Precio rn
BN 12/01/2008 100 1
BN 01/03/2009 105 2
BN 01/04/2009 200 3

Ahora, si unimos (join) este resultado intermedio consigo mismo, mediante
la
expresion a.ID = b.ID and a.rn = b.rn - 1, estariamos uniendo

BN(1) - BN(2)
BN(2) - BN(3)

y por tanto, la fecha final de cada fila en el lado izquierdo (llamemosle
"a"), seria la fecha de inicio de el lado "b" menos un dia. Aqui hacemos
lo
mismo para las filas que son la ultima en su grupo, le asignamos como
fecha
final su propia fecha de inicio. Ejemplo:

ID Fecha_Inicio Fecha_Fin Precio
BN 01/04/2009 01/04/2009 200

;WITH r_set
AS
(
ID,
Fecha_Inicio,
Precio,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Fecha_Inicio) AS rn
FROM
T2
),
FechaRango
AS
(
SELECT
a.ID,
a.Fecha_Inicio,
ISNULL(DATEADD([day], -1, b.Fecha_Inicio), a.Fecha_Inicio) AS Fecha_Fin,
a.Precio
FROM
r_set AS a
LEFT OUTER JOIN
r_Set AS b
ON a.ID = b.ID
AND a.rn = b.rn - 1
)
UPDATE
a
SET
a.Precio = fr.Precio
FROM
T1 AS a
INNER JOIN
FechaRango AS fr
ON a.ID = fr.ID
AND a.Fecha_Inicio BETWEEN fr.Fecha_Inicio AND Fecha_Fin;
GO

Debido a la complejidad de solucion que usa la funcion row_number,
posiblemente su desempenio este a la par de la solucion que usa query
correlacionado, si el # de filas no es mucho.


AMB


"DT" wrote:

Hola
Tengo dos tablas, T1 y T2. T1 Tiene los campos de Fecha y Valor, fecha
corresponde a una lista de fechas que puede ser un mes entero, un ao
entero
(en orden), Valor es un campo vaco que debe tener los valores de T2.

Tengo una tabla con este contenido:
ID Fecha Valor
BN 01/01/2009 NULL
BN 01/02/2009 NULL
BN 01/03/2009 NULL
BN 01/04/2009 NULL
...

La T2 tiene los siguientes campos:
ID Fecha_Inicio PRECIO
BN 12/01/2008 100
BN 01/03/2009 105
BN 01/04/2009 200

Tengo que tener este resultado en T1
ID Fecha Valor
BN 01/01/2009 100
BN 01/02/2009 100
BN 01/03/2009 105
BN 01/04/2009 200

El pseudocdigo sera:
Actualizar T1 - Poner en VALOR
(
El PRECIO desde la Fecha de INICIO hasta la FECHA de Cada producto)

Sabiendo que la fecha de inicio siguiente -1 es la fecha en que termina
el
producto (campo no existe)

1000 gracias, espero haber sido claro... :_)

Respuesta Responder a este mensaje
#4 Alejandro Mesa
13/03/2009 - 22:08 | Informe spam
Maestro?

Ya quiciera yo, me falta mucho para llegar a esa categoria.

AMB



"DT" wrote:

muchas gracias, maestro!

"Alejandro Mesa" wrote in message
news:
> DT,
>
> Cual es la version de SQL Server que usas?
>
> Aqui expongo dos posibles soluciones. La primera usa un subquery
> correlacionado para encontrar la fecha final de cada fila en T2. La
> segunda
> usa la funcion row_number() para encontrar la fecha fin.
>
> Si por casualidad usas una version de SQL Server menor a 2005, entonces
> tendras que lidear con la primera propuesta, solo debes usar la sentencia
> que
> define la CTE como una tabla derivada.
>
>
> ;WITH fechaRango
> AS
> (
> SELECT
> a.ID,
> a.Fecha_Inicio,
> ISNULL(
> (
> SELECT
> DATEADD([day], -1, MIN(b.Fecha_Inicio))
> FROM
> T2 AS b
> WHERE
> b.[ID] = a.[ID]
> AND b.Fecha_Inicio > a.Fecha_Inicio
> AND b.Precio <> a.Precio
> ), Fecha_Inicio) AS Fecha_Fin,
> a.Precio
> FROM
> T2 AS a
> )
> UPDATE
> a
> SET
> a.Precio = fr.Precio
> FROM
> T1 AS a
> INNER JOIN
> FechaRango AS fr
> ON a.ID = fr.ID
> AND a.Fecha_Inicio BETWEEN fr.Fecha_Inicio AND Fecha_Fin;
> GO
>
> Deja ver si explico la idea sin confundir al lector. Para cada fila en T2,
> haya la minima fecha de inicio de las filas que tienen igual ID a la fila
> que
> se procesa, cuyo valor de la columna precio es diferente al precio de la
> fila
> que procesamos. Le restamos un dia a dicha fecha y obtenemos la fecha fin
> de
> esa fila. Si la fila es la ultima en su grupo, entonces usamos su propia
> fecha de inicio como la fecha fin.
>
> Basado en tu data de ejemplo (hombre un esfuerzito para poner un par mas
> de
> filas, al menos un par mas de IDs), tendriamos:
>
> ID Fecha_Inicio Fecha_Fin Precio
> BN 12/01/2008 01/02/2009 100
> BN 01/03/2009 01/03/2009 105
> BN 01/04/2009 01/04/2009 200
>
> Ahora solo basta unir la tabla T1 con este resultado, usando el operador
> BETWEEN.
>
> Casi siempre, los subqueries correlacionados tienden a disminuir el
> desempenio de un query, sobre todo si el numero de filas para el cual
> debemos
> ejecutar el subquery aumenta. Asi que expongo otra posible solucion, que
> usa
> la funcion row_number para asignar un # a cada fila, particionando las
> filas
> por ID y ordenandolas por la fecha de inicio. Basado en tu data de ejemplo
> tendriamos un resultado intermedio como:
>
> ID Fecha_Inicio Precio rn
> BN 12/01/2008 100 1
> BN 01/03/2009 105 2
> BN 01/04/2009 200 3
>
> Ahora, si unimos (join) este resultado intermedio consigo mismo, mediante
> la
> expresion a.ID = b.ID and a.rn = b.rn - 1, estariamos uniendo
>
> BN(1) - BN(2)
> BN(2) - BN(3)
>
> y por tanto, la fecha final de cada fila en el lado izquierdo (llamemosle
> "a"), seria la fecha de inicio de el lado "b" menos un dia. Aqui hacemos
> lo
> mismo para las filas que son la ultima en su grupo, le asignamos como
> fecha
> final su propia fecha de inicio. Ejemplo:
>
> ID Fecha_Inicio Fecha_Fin Precio
> BN 01/04/2009 01/04/2009 200
>
> ;WITH r_set
> AS
> (
> ID,
> Fecha_Inicio,
> Precio,
> ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Fecha_Inicio) AS rn
> FROM
> T2
> ),
> FechaRango
> AS
> (
> SELECT
> a.ID,
> a.Fecha_Inicio,
> ISNULL(DATEADD([day], -1, b.Fecha_Inicio), a.Fecha_Inicio) AS Fecha_Fin,
> a.Precio
> FROM
> r_set AS a
> LEFT OUTER JOIN
> r_Set AS b
> ON a.ID = b.ID
> AND a.rn = b.rn - 1
> )
> UPDATE
> a
> SET
> a.Precio = fr.Precio
> FROM
> T1 AS a
> INNER JOIN
> FechaRango AS fr
> ON a.ID = fr.ID
> AND a.Fecha_Inicio BETWEEN fr.Fecha_Inicio AND Fecha_Fin;
> GO
>
> Debido a la complejidad de solucion que usa la funcion row_number,
> posiblemente su desempenio este a la par de la solucion que usa query
> correlacionado, si el # de filas no es mucho.
>
>
> AMB
>
>
> "DT" wrote:
>
>> Hola
>> Tengo dos tablas, T1 y T2. T1 Tiene los campos de Fecha y Valor, fecha
>> corresponde a una lista de fechas que puede ser un mes entero, un ao
>> entero
>> (en orden), Valor es un campo vaco que debe tener los valores de T2.
>>
>> Tengo una tabla con este contenido:
>> ID Fecha Valor
>> BN 01/01/2009 NULL
>> BN 01/02/2009 NULL
>> BN 01/03/2009 NULL
>> BN 01/04/2009 NULL
>> ...
>>
>> La T2 tiene los siguientes campos:
>> ID Fecha_Inicio PRECIO
>> BN 12/01/2008 100
>> BN 01/03/2009 105
>> BN 01/04/2009 200
>>
>> Tengo que tener este resultado en T1
>> ID Fecha Valor
>> BN 01/01/2009 100
>> BN 01/02/2009 100
>> BN 01/03/2009 105
>> BN 01/04/2009 200
>>
>> El pseudocdigo sera:
>> Actualizar T1 - Poner en VALOR
>> (
>> El PRECIO desde la Fecha de INICIO hasta la FECHA de Cada producto)
>>
>> Sabiendo que la fecha de inicio siguiente -1 es la fecha en que termina
>> el
>> producto (campo no existe)
>>
>> 1000 gracias, espero haber sido claro... :_)
>>

email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida