|
|
||||||
|
#1
|
|
|
|
|
Hola a todos,
Tengo una tabla con la siguiente estructura: Proveedor, RefProv, EAN, Descripcion, Precio, PrecioNeto En ella importo datos de las tarifas de diferentes proveedores. Tengo entre 1000 y 2000 filas por proveedor, y artículos cuyo código EAN coincide entre diversos proveedores (a priori no sé cuantos). La PK de esta tabla es Proveedor+RefProv Lo que necesito es hacer una consulta que me devuelva: EAN, Descripcion, "PrecioNeto de cada proveedor". Por tanto necesito las dos primeras columnas más una por cada PrecioNeto, en función de cuantos proveedores tengan ese código EAN. La verdad que no se me ocurre como obtener ese número de columnas variable, y además tengo que hacerlo para SQL Server 2000. Pd. También me interesaría ver la solución con 2005 para compararla (pero vamos esto es opcional). Pd2. Siempre me queda la alternativa de montar un cubo muy sencillo sobre esa tabla, pero me gustaría optar por una solución en el relacional :-) |
|
|
|
#2
|
|
|
|
|
Hola Salvador,
Te paso una forma de resolverlo con SQL 2000, usando un SP que genera una cantidad dinámica de columnas, no es mío, es de esas cosas que uno copia y pega desde el foro. No puedo decirte si es bueno el rendimiento porque las veces que lo necesité fue para usarlo con menos de 10 millones de filas. Espero que te sirva, Liliana. DROP Procedure #Proc_Query_Pivot_1 GO CREATE Procedure #proc_Query_Pivot_1 @Datos_Base_SQL varchar(2000), -- SQL que devuelve datos para la construcción de la tabla cruzada @Encabe_Fila varchar(200), -- Lista de filas para usar como dato de agrupamiento @Encabe_Columna varchar(200), -- Nombre del dato que se usará como encabezado de columna @Titulo_Columna_SQL varchar(2000), -- SQL que devuelve los posibles encabezados @Operacion varchar(10), -- SUM, PRODUCT, etc @Argumento varchar(200), -- Columna argumento de la operacion @Totales char(1) -- 'S' incluye totales generales, 'N' los omite AS Declare @SQL varchar(2000), @Summary_SQL varchar(2000) -- to summarize each row Set @SQL = 'SELECT ' + @Encabe_Fila + ', ' Set @Summary_SQL = '' -- Obtener lista de encabezamiento de columnas CREATE TABLE #Col_Encabes (Col_ID int identity(1,1), Col_Encabe varchar(200) NULL) Exec ('INSERT INTO #Col_Encabes (Col_Encabe) ' + @Titulo_Columna_SQL) -- select * from #Col_Encabes -- debug -- Recorre todas las columnas, construye pivot DECLARE @Col_ID_Curr int, -- columna chequeada @Col_ID_Old int, @Curr_Col_Encabe varchar(200), @Pivot_SQL varchar(200) -- pivot SQL para la columna SELECT TOP 1 @Col_ID_Curr = Col_ID, @Curr_Col_Encabe = Col_Encabe FROM #Col_Encabes ORDER BY Col_ID IF (@Col_ID_Curr IS NOT NULL ) BEGIN -- para entrar en el while Set @Col_ID_Old = @Col_ID_Curr - 1 WHILE (@Col_ID_Old <> @Col_ID_Curr) BEGIN -- print 'Agrega linea de pivot ' + @Curr_Col_Encabe -- debug Set @Pivot_SQL = char(13) + @Operacion + '(CASE ' + @Encabe_Columna + ' WHEN ''' + @Curr_Col_Encabe + ''' THEN ' + @Argumento + ' ELSE SPACE(2) END) AS [' + @Curr_Col_Encabe + ']' Set @SQL = @SQL + ' ' + @Pivot_SQL -- Agrega columna de totales If (@Totales='S') Set @Summary_SQL = @Summary_SQL + 'Pivot_Data.[' + @Curr_Col_Encabe + ']' -- Obtiene el próximo encabezamiento de columna -- Si no hay más Col_Encabes en la tabla, el select no devuelve filas -- y Col_ID_Curr no cambia - sale del while Set @Col_ID_Old = @Col_ID_Curr SELECT TOP 1 @Col_ID_Curr = Col_ID, @Curr_Col_Encabe = Col_Encabe FROM #Col_Encabes WHERE Col_ID > @Col_ID_Curr ORDER BY Col_ID -- Agrega delimitadores a la lista IF (@Col_ID_Old <> @Col_ID_Curr) Begin Set @SQL = @SQL + ', ' Set @Summary_SQL = @Summary_SQL + ' + ' End END END -- Libera objetos DROP TABLE #Col_Encabes -- Termina la sentencia SQL Set @SQL = @SQL + char(13) + 'FROM (' + @Datos_Base_SQL + ') AS Datos_Base ' + char(13) + 'GROUP BY ' + @Encabe_Fila -- Si se requiere totales, los agrega en la sentencia SQL construída If (@Totales='S') Set @SQL = 'SELECT Pivot_Data.*, ' + char(13) + ' (' + @Summary_SQL + ') AS TOTAL ' + char(13) + 'FROM (' + @SQL + ') AS Pivot_Data' -- Terminado Print @SQL Select '' Exec (@SQL) go -- Ejecucion del Stored Procedure EXEC #proc_Query_Pivot_1 -- parametros: -- select de la informacion a utilizar -- si fuera una sola tabla seria "select miscampos from mitabla where micondicion" 'SELECT Proveedor, EAN, Descripcion, Precio FROM #Prov', -- Encabezamiento de primera columna 'EAN', -- Nombre dato del encabezamiento del resto de las columnas 'Proveedor', -- encabezados de columnas 'SELECT DISTINCT Proveedor FROM #Prov', -- funcion de agregado a realizar (SUM, AVG, MAX, MIN, etc), 'MAX', -- nombre de columna afectada por la funcion anterior 'Precio', -- si se totaliza o no el renglon 'n' "Salvador Ramos" <webmasterEstoSobra> escribió en el mensaje news:a960 [..] |
|
#3
|
|
|
|
|
Muchas gracias Liliana,
Resuelve perfectamente el problema planteado, y no me preocupa el rendimiento, ya que la tabla origen de los datos no superará las 10.000 filas. Ahora lo que me preocupa es que el usuario empezará a pedirme variantes sobre estos resultados, querrá hacer join con la tabla de Articulos por la columna CodBarras para obtener columas de dicha tabla, obtener el precio más bajo entre todas las columnas y demás. Así que voy a hablar con él, y si es como intuyo, basandome en lo que me has enviado voy a crear una nueva tabla que se actualice periódicamente y así poder utilizarla con mayor flexibilidad. Para ello en las prueba he modificado la siguiente línea añadiendo INTO #T1 Set @SQL = @SQL + char(13) + ' INTO #T1 FROM (' + @Datos_Base_SQL + ') AS Datos_Base Creo que voy a optar por hacerlo así, ya que es una tabla que se actualiza con muy poca frecuencia y se consulta mucho. |
|
#4
|
|
|
|
|
Habría alguna solución sin usar sql dinámico en 2005 ?
|
|
#5
|
|
|
|
|
Hola Salvador:
Puedes usar el comando PIVOT, pero este no es dinamico es fijo, de manera que siempre tendar que hacer SQL Dinamico, pero mucho mucho mas sencillo. Un ejemplo de como hacer un PIVOT con AdventureWorks; ==================== SELECT * FROM (SELECT SalesPersonID , SubTotal , YEAR(OrderDate) AS Year FROM Sales.SalesOrderHeader ) AS Base PIVOT ( SUM(SubTotal) FOR [Year] IN ([2002], [2003], [2004]) ) AS pvt; ==================== En el caso que quisieras los años dinamicos hay que construir el comando con SQL Dinamico para generar la lista de las columnas con un SELECT DISTINCT de los años. Claro que la solucion, como bien lo dijiste es, ..... UN CUBO!!!! ;-) Saludos y a ver si nos vemos durante en el Summit. Javier Loria Costa Rica (MVP) Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.) que pueda ser copiado y pegado al Query Analizer. La version de SQL y Service Pack tambien ayuda. "Salvador Ramos" <webmasterEstoSobra> wrote in message news:4568 [..] |
|
#6
|
|
|
|
|
Muchas gracias Javier,
Más que nada era por confirmar que no se me había pasado alguna forma de evitar el sql dinámico. Efectivamente, voy a buscar una solución a corto plazo basada en el relacional sobre 2000. Y me voy a plantear un cubo más tranquilamente, que ofrezca toda la información necesaria de una forma más flexible. Claro que si, nos vemos en el Summit, que ya está cerquita :-) Pd. Si queréis saber a qué Summit nos referimos Javier y yo, aquí tenéis un link http://learning.solidq.com/ib/Course...ScheduleId=215 |
|
|
| Temas Similares | |
| Pivotar un select Hola a todos. Existe alguna manera de pivotar el contenido de un select? por ejemplo, si hago un "select * from tabla" tengo lo siguiente: ID Campo ID_de_campo 1 ... |
|
| pivotar Hola buenos dias me gustaria conocer como puedo pivotar una misma columna 2 veces en una query. Esplico mejor: Pivotar una vez para que me sume las cantidades, y pivotar una... |
|
| pivotar solo media tabla Hola Sé como pivotar una tabla entera pero...¿que pasa cuando lo que quiero es pivotar solo una parte de la tabla? La tabla es la siguiente: cliente banco fecha... |
|
| Pivotar Muy buenas. Tengo una duda y voy a intentar explicarla con un ejemplo: Tengo 2 tablas y quiero cruzarlas para ver las diferencias que tienen, pero el problema es que su... |
|
| PIVOTAR TABLA SIN AGREGADOS Hola: Anteriormente ya pregunté acerca de la posibilidad de convertir las columnas en filas y las filas en columnas. Lo que habitualmente se denomina "pivotar"o "rotar" una... |
|
|
La franja horaria es GMT. Ahora son las 19:52. | Privacy Policy
|