Principales respuestas
Unir 2 tablas por el campo fecha y mostrar un valor por el rango de la fecha en una consulta

Pregunta
-
lunes, 12 de septiembre de 2016 16:11
Respuestas
-
Acabo de notar que hay un error en la definición del limite máximo, provoca duplicidad cuando la fecha para un valor de la columna 'NumOrdenm' coincide con una fecha de valor de moneda.
Prueba con la siguiente consulta:
WITH ValorMoedaDia AS ( SELECT t.ValorMoedaDia, (base / valormoedadia) as TC, t.DataMovtoMoeda, ROW_NUMBER() OVER(ORDER BY t.DataMovtoMoeda asc) AS R FROM FIN_MovtoMoeda t ) SELECT v.DtRefMoeda AS 'FechaVenta', (1 / t1.ValorMoedaDia) AS 'ValorMoneda' FROM ValorMoedaDia t1 LEFT JOIN ValorMoedaDia t2 ON (t1.R = t2.R-1) INNER JOIN OrcHdr v ON (v.DtRefMoeda BETWEEN t1.DataMovtoMoeda AND ISNULL(DATEADD(DAY, -1, t2.DataMovtoMoeda), GETDATE())) WHERE v.NumOrdem IN ('38038')
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.- Propuesto como respuesta Edu Martinez martes, 13 de septiembre de 2016 22:52
- Votado como útil Laura CeglzModerator viernes, 16 de septiembre de 2016 18:03
- Marcado como respuesta Laura CeglzModerator viernes, 16 de septiembre de 2016 18:03
martes, 13 de septiembre de 2016 21:43 -
Claro que si, aunque está demás la aclaración entiendo que el filtro por la columna 'NumOrdem' lo harás sobre la vista, ¿verdad?. Para ello debes de colocar la columna en la lista de selección:
/*Definición de la vista*/ CREATE VIEW dbo.MiVista AS WITH ValorMoedaDia AS ( SELECT t.ValorMoedaDia, (base / valormoedadia) as TC, t.DataMovtoMoeda, ROW_NUMBER() OVER(ORDER BY t.DataMovtoMoeda asc) AS R FROM FIN_MovtoMoeda t ) SELECT v.NumOrdem AS 'NumOrdem', v.DtRefMoeda AS 'FechaVenta', (1 / t1.ValorMoedaDia) AS 'ValorMoneda' FROM ValorMoedaDia t1 LEFT JOIN ValorMoedaDia t2 ON (t1.R = t2.R-1) INNER JOIN OrcHdr v ON (v.DtRefMoeda BETWEEN t1.DataMovtoMoeda AND ISNULL(DATEADD(DAY, -1, t2.DataMovtoMoeda), GETDATE())) GO /*Invocación de la vista*/ SELECT * FROM dbo.MiVista WHERE (NumOrdem = '38038')
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.- Propuesto como respuesta Edu Martinez martes, 13 de septiembre de 2016 22:52
- Marcado como respuesta Laura CeglzModerator viernes, 16 de septiembre de 2016 18:02
martes, 13 de septiembre de 2016 22:21 -
Hombre, que trabajo te cuesta dar un poco de ayuda.
Si tienes SS 2012 o mayor, entonces puedes usar:
DECLARE @T1 table ( col1 int NOT NULL, col2 char(1) NOT NULL ); DECLARE @T2 table ( col1 int NOT NULL ); INSERT INTO @T1 (col1, col2) VALUES (1, 'a'), (3, 'b'), (8, 'c'), (12, 'd'), (16, 'w'), (20, 'f'); INSERT INTO @T2 (col1) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20); -- para que veas valores devueltos por la CTE --SELECT -- col1 AS desde, -- ISNULL(LEAD(col1) OVER(ORDER BY col1) - 1, col1) AS hasta, -- col2 --FROM -- @T1 --ORDER BY -- col1; WITH R AS ( SELECT col1 AS desde, ISNULL(LEAD(col1) OVER(ORDER BY col1) - 1, col1) AS hasta, col2 FROM @T1 ) SELECT T.col1, R.col2 FROM @T2 AS T INNER JOIN R ON T.col1 BETWEEN R.desde AND R.hasta; GO
La idea es hacer un pase por T1 y capturar el valor de [col1] para la fila sgte dado el orden por [col1].
desde hasta col2 1 2 a 3 7 b 8 11 c 12 15 d 16 19 w 20 20f
Como vez, esto nos permite calcular el rango de valores por cada fila de T1. El resto es unir la CTE con T2 usando union de rango.
Noto que Willams tiene una sugerencia. Lo primero que hace es la union y despues la enumeracion, por lo que con esta data de ejemplo serian 66 filas a ordenar para poder enumerar. Para una tabla pequenia no sera problema pero si para tablas con un numero de filas considerable.
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas
- Editado HunchbackMVP lunes, 12 de septiembre de 2016 19:16
- Propuesto como respuesta Willams Morales lunes, 12 de septiembre de 2016 19:20
- Marcado como respuesta Laura CeglzModerator viernes, 16 de septiembre de 2016 18:02
lunes, 12 de septiembre de 2016 19:03
Todas las respuestas
-
Quiero hacer un query, que me pueda mostrar la segunda tabla con el campo valor de la primera.lunes, 12 de septiembre de 2016 17:20 -
Trata:
select A.*, B.*
from T1 as A inner join T2 as B on A.fecha = B.fecha
where A.fecha between '20160101' and '20160131';Si la manera de unir ambas tablas es usando un equi-join (igualdad) entonces puedes poner el filtro en cualquier lado de la union (T1 o T2). Si quieres que uno de los lados prevalezca, entonces el filtro debera ir de ese lado.
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntaslunes, 12 de septiembre de 2016 17:28 -
Hola,
Si te das cuenta en la primera tabla no tengo la fecha 2. de la 1 se pasa a la 3 pero en la segunda tabla si tengo la fecha 2. Entonces la lógica es que debe respetar el rango de la columna. hasta que haya un cambio de fecha y sea igual o mayor hasta el siguiente cambio. No se si me dejo explicar.
lunes, 12 de septiembre de 2016 17:34 -
Miguel,
Es dificil comprender lo que se quiere solo siguiendo la descripcion. Para estos casos es preferible que adjuntes las sentencias SQL para definir las tablas, data de ejemplo en forma de sentencias INSERT, asi como el resultado esperado. De esta manera tendremos algo con que comprobar y no tendremos que mal gastar nuestro tiempo replicando tu ambiente.
Ayudanos para poder ayudarte!
Si es que comprendi correctamente, entonces:
select A.*, B.*
from T1 as A right outer join T2 as B on A.fecha = B.fecha
where B.fecha between '20160101' and '20160131';
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas- Editado HunchbackMVP lunes, 12 de septiembre de 2016 17:44
lunes, 12 de septiembre de 2016 17:43 -
Los registro de la tabla 1 tengo datos por rango de fechas por ejemplo de la fecha 3 hasta la fecha 7 debe tener el valor "b", en la fecha 8 ya cambia al valor a "C" y este valor sera hasta la fecha 11 en la 12 ya hay cambio.
El query, debe hacer que al siguiente registro debe validar si corresponde o no al rango de fechas.
lunes, 12 de septiembre de 2016 17:47 -
Lo resaltado en verde es lo que debo obtener con el query. Segun los rangos de la primera tabla.lunes, 12 de septiembre de 2016 17:49
-
Puedes hacer lo siguiente:
WITH CTE AS ( SELECT t2.Fecha AS 'Fecha', t1.Valor AS 'Valor', ROW_NUMBER() OVER(PARTITION BY t2.Fecha ORDER BY t1.Fecha DESC) AS 'Fila' FROM Tabla2 t2 LEFT JOIN Tabla1 t1 ON (t2.Fecha >= t1.Fecha) ) SELECT Fecha, Valor FROM CTE WHERE Fila = 1;
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.lunes, 12 de septiembre de 2016 17:54 -
Hombre, que trabajo te cuesta dar un poco de ayuda.
Si tienes SS 2012 o mayor, entonces puedes usar:
DECLARE @T1 table ( col1 int NOT NULL, col2 char(1) NOT NULL ); DECLARE @T2 table ( col1 int NOT NULL ); INSERT INTO @T1 (col1, col2) VALUES (1, 'a'), (3, 'b'), (8, 'c'), (12, 'd'), (16, 'w'), (20, 'f'); INSERT INTO @T2 (col1) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20); -- para que veas valores devueltos por la CTE --SELECT -- col1 AS desde, -- ISNULL(LEAD(col1) OVER(ORDER BY col1) - 1, col1) AS hasta, -- col2 --FROM -- @T1 --ORDER BY -- col1; WITH R AS ( SELECT col1 AS desde, ISNULL(LEAD(col1) OVER(ORDER BY col1) - 1, col1) AS hasta, col2 FROM @T1 ) SELECT T.col1, R.col2 FROM @T2 AS T INNER JOIN R ON T.col1 BETWEEN R.desde AND R.hasta; GO
La idea es hacer un pase por T1 y capturar el valor de [col1] para la fila sgte dado el orden por [col1].
desde hasta col2 1 2 a 3 7 b 8 11 c 12 15 d 16 19 w 20 20f
Como vez, esto nos permite calcular el rango de valores por cada fila de T1. El resto es unir la CTE con T2 usando union de rango.
Noto que Willams tiene una sugerencia. Lo primero que hace es la union y despues la enumeracion, por lo que con esta data de ejemplo serian 66 filas a ordenar para poder enumerar. Para una tabla pequenia no sera problema pero si para tablas con un numero de filas considerable.
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas
- Editado HunchbackMVP lunes, 12 de septiembre de 2016 19:16
- Propuesto como respuesta Willams Morales lunes, 12 de septiembre de 2016 19:20
- Marcado como respuesta Laura CeglzModerator viernes, 16 de septiembre de 2016 18:02
lunes, 12 de septiembre de 2016 19:03 -
Rayos!, claro!, lo mejor es subir la fila siguiente como rango limitante de la fila actual y evitar lecturas innecesarias, ¿cómo no lo pensé antes?. Gracias AMB por la aclaración, de hecho tu propuesta es el camino a tomar.lunes, 12 de septiembre de 2016 19:19
-
Gracías por tus palabras, Willams!
Esa sugerencia solo le servira si usa SS 2012 o mayor. Para versiones menores debera usar una de las soluciones aceptables para calcular el rango del hueco.
Por ejemplo:
WITH R AS ( SELECT col1, col2, ROW_NUMBER() OVER(ORDER BY col1) AS rn FROM @T1 ) SELECT A.col1 AS desde, ISNULL(B.col1 - 1, A.col1) AS hasta, A.col2 FROM R AS A LEFT OUTER JOIN R AS B ON A.rn = B.rn - 1 GO
Pero como vez, habria que enumerar dos veces, asi que seria mejor enumerar y guardar el resultado en una tabla para luego usar esta en la union.
La simplicidad de usar LEAD se desecha comparado con versiones anteriores.
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntaslunes, 12 de septiembre de 2016 19:34 -
Muchas muchas gracias, estoy tratando de hacer el query con la primera ayuda de Willams, pero cuando consulta más de 200 registros no me sale todo. Les adjunto mi tabla real y quizás entienda mi problemática. Esta tabla almacena el valor de la moneda en el día, este valor puede mantener así por unos días, semana o mes hasta que cambie para lo que se necesita ingresar otro registro, como se muestran en la imagen, el ultimo ingreso a sido el 07/09/2016 con su valorMoedaDia 0.2967359.
Ahora lo que quiero es llevar este valor a otro tabla que tienen muchos registros y relacionarlos por el campo DataMovtoMoeda y el campo fecha de esta segunda tabla. El tema es que la segunda tabla tiene todas las fechas diarias no por rangos como la primera tabla. En la consulta debo mostrar todas los registros con estas fechas con su valorMoedadia. Siguiendo el ejemplo del ultimo registro de la primera tabla. Si mi consulta será por los rangos de fechas de la segunda tabla, que estos sean mayores a 07/09/2016 los registros del 07/09/2016 hasta hoy me deberan mostrar el valor 0.2967359 si mañana registrara un nuevo valor en la primera tabla, cuando consulte mañana los registros que tenga después del 12/09/2016 tendrán ese valor nuevo. No si si la solución de AMB es la que necesito haré pruebas igual. Muchas Gracias !!!
Tengo SQL 2008
- Editado Miguel Jose Luis lunes, 12 de septiembre de 2016 20:07
lunes, 12 de septiembre de 2016 20:05 -
Presentas una versión del motor de SQL Server anterior a la versión 2012 por tanto no podrás hacer uso de la función LEAD() que propone AMB, así que habrá que acomodar tu caso en función de la segunda propuesta:
DECLARE @ValorMoneda table (ValorMoedaDia decimal(12,7), DataMovtoMoeda date); DECLARE @Ventas table (Fecha date); INSERT INTO @ValorMoneda VALUES (0.3225807, '20/03/2015'), (0.3184713, '21/04/2015'), (0.3164557, '06/06/2015'), (0.3134796, '06/07/2015'), (0.3095975, '14/08/2015'), (0.3030303, '24/08/2015'), (0.3067485, '07/09/2015'), (0.3105590, '17/09/2015'), (0.3067485, '21/10/2015'), (0.2985075, '17/11/2015'); INSERT INTO @Ventas VALUES ('15/07/2015'), ('10/10/2015'), ('28/10/2015'); WITH ValorMoneda AS ( SELECT t.ValorMoedaDia, t.DataMovtoMoeda, ROW_NUMBER() OVER(ORDER BY t.DataMovtoMoeda) AS R FROM @ValorMoneda t ) SELECT v.Fecha AS 'FechaVenta', t1.ValorMoedaDia AS 'ValorMoneda' FROM ValorMoneda t1 LEFT JOIN ValorMoneda t2 ON (t1.R = t2.R-1) INNER JOIN @Ventas v ON (v.Fecha BETWEEN t1.DataMovtoMoeda AND ISNULL(t2.DataMovtoMoeda, GETDATE()))
Tengo dos tablas, la primera es donde se encuentra los valores de moneda en el tiempo y una segunda tabla de ventas donde sólo agrego una columna de fecha de venta, la consulta intersecta un valor de moneda para la fecha de venta.
Como sugerencia a un caso posterior, es recomendable que nos postees data de ejemplo para recrear el caso, pero no como imagen (no tengo disponible un lector OCR) sino como instrucciones INSERT, danos una mano para poder ayudarte.
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.martes, 13 de septiembre de 2016 4:10 -
Hola Willams, estas muy cerca de lo que necesito, solo que cuando hago agrego un where in con una lista de productos algunos me sale 2 registros cuando solo tienen una fecha de venta. Los productos son únicos.martes, 13 de septiembre de 2016 21:12
-
¿Podrías mostrar el código sql que tienes desarrollado?
Créeme que con la sola descripción del problema no podría decirte con total certeza el error que cometes, al parecer estás realizando un JOIN con alguna tabla (presumiblemente los detalles de la venta) que hace que los resultados se multipliquen según las filas que hacen match.
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.martes, 13 de septiembre de 2016 21:16 -
WITH ValorMoedaDia AS ( SELECT t.ValorMoedaDia, (base / valormoedadia) as TC, t.DataMovtoMoeda, ROW_NUMBER() OVER(ORDER BY t.DataMovtoMoeda asc) AS R FROM FIN_MovtoMoeda t ) SELECT v.DtRefMoeda AS 'FechaVenta', (1 / t1.ValorMoedaDia) AS 'ValorMoneda' FROM ValorMoedaDia t1 left JOIN ValorMoedaDia t2 ON (t1.R = t2.R-1) inner JOIN OrcHdr v ON (v.DtRefMoeda between t1.DataMovtoMoeda AND ISNULL(t2.DataMovtoMoeda , GETDATE())) where v.NumOrdem in ('38038') select * from OrcHdr where NumOrdem = '38038'
martes, 13 de septiembre de 2016 21:24 -
La tabla OrcHdr tiene registros unicos por NumOrdem no se repiten, pero si puedo tener la misma dtRefMoeda para varias numordem.martes, 13 de septiembre de 2016 21:26
-
martes, 13 de septiembre de 2016 21:35
-
Acabo de notar que hay un error en la definición del limite máximo, provoca duplicidad cuando la fecha para un valor de la columna 'NumOrdenm' coincide con una fecha de valor de moneda.
Prueba con la siguiente consulta:
WITH ValorMoedaDia AS ( SELECT t.ValorMoedaDia, (base / valormoedadia) as TC, t.DataMovtoMoeda, ROW_NUMBER() OVER(ORDER BY t.DataMovtoMoeda asc) AS R FROM FIN_MovtoMoeda t ) SELECT v.DtRefMoeda AS 'FechaVenta', (1 / t1.ValorMoedaDia) AS 'ValorMoneda' FROM ValorMoedaDia t1 LEFT JOIN ValorMoedaDia t2 ON (t1.R = t2.R-1) INNER JOIN OrcHdr v ON (v.DtRefMoeda BETWEEN t1.DataMovtoMoeda AND ISNULL(DATEADD(DAY, -1, t2.DataMovtoMoeda), GETDATE())) WHERE v.NumOrdem IN ('38038')
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.- Propuesto como respuesta Edu Martinez martes, 13 de septiembre de 2016 22:52
- Votado como útil Laura CeglzModerator viernes, 16 de septiembre de 2016 18:03
- Marcado como respuesta Laura CeglzModerator viernes, 16 de septiembre de 2016 18:03
martes, 13 de septiembre de 2016 21:43 -
Gracias!!! Willanms, con este código tengo lo que que necesito. Dime podría crear una vista con este código para poder usarlo siempre?
Muchas gracias por tu ayuda.
Saludos
Miguel
martes, 13 de septiembre de 2016 22:05 -
Claro que si, aunque está demás la aclaración entiendo que el filtro por la columna 'NumOrdem' lo harás sobre la vista, ¿verdad?. Para ello debes de colocar la columna en la lista de selección:
/*Definición de la vista*/ CREATE VIEW dbo.MiVista AS WITH ValorMoedaDia AS ( SELECT t.ValorMoedaDia, (base / valormoedadia) as TC, t.DataMovtoMoeda, ROW_NUMBER() OVER(ORDER BY t.DataMovtoMoeda asc) AS R FROM FIN_MovtoMoeda t ) SELECT v.NumOrdem AS 'NumOrdem', v.DtRefMoeda AS 'FechaVenta', (1 / t1.ValorMoedaDia) AS 'ValorMoneda' FROM ValorMoedaDia t1 LEFT JOIN ValorMoedaDia t2 ON (t1.R = t2.R-1) INNER JOIN OrcHdr v ON (v.DtRefMoeda BETWEEN t1.DataMovtoMoeda AND ISNULL(DATEADD(DAY, -1, t2.DataMovtoMoeda), GETDATE())) GO /*Invocación de la vista*/ SELECT * FROM dbo.MiVista WHERE (NumOrdem = '38038')
Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.- Propuesto como respuesta Edu Martinez martes, 13 de septiembre de 2016 22:52
- Marcado como respuesta Laura CeglzModerator viernes, 16 de septiembre de 2016 18:02
martes, 13 de septiembre de 2016 22:21