hilpers


  hilpers > microsoft.* > microsoft.sqlserver

 #1  
15-05-2007, 17:08
Salvador Ramos
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  
15-05-2007, 19:45
Liliana Sorrentino
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  
16-05-2007, 09:22
Salvador Ramos
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  
16-05-2007, 10:16
Salvador Ramos
Habría alguna solución sin usar sql dinámico en 2005 ?
 #5  
16-05-2007, 14:49
Javier Loria
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  
16-05-2007, 15:10
Salvador Ramos
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