2010-11-02 7 views
9

Necesito crear una vista desde varias tablas. Una de las columnas en la vista tendrá que estar compuesta de varias filas de una de las tablas como una cadena con valores separados por comas.Uso de COALESCE en la vista de SQL

Aquí hay un ejemplo simplificado de lo que quiero hacer.

Customers: 
CustomerId int 
CustomerName VARCHAR(100) 

Orders: 
CustomerId int 
OrderName VARCHAR(100) 

Hay una relación de uno a muchos entre Cliente y Pedidos. Así que dado estos datos

Customers 
1 'John' 
2 'Marry' 

Orders 
1 'New Hat' 
1 'New Book' 
1 'New Phone' 

quiero miras a ser así:

Name  Orders 
'John' New Hat, New Book, New Phone 
'Marry' NULL 

por lo que todo el mundo se muestra en la tabla, independientemente de si tienen o no órdenes.

Tengo un procedimiento almacenado que necesito traducir a esta vista, pero parece que no puede declarar params y llamar a los procesos almacenados dentro de una vista. ¿Alguna sugerencia sobre cómo hacer que esta consulta se visualice?

CREATE PROCEDURE getCustomerOrders(@customerId int) 
AS 
    DECLARE @CustomerName varchar(100) 
    DECLARE @Orders varchar (5000) 

    SELECT @Orders=COALESCE(@Orders,'') + COALESCE(OrderName,'') + ',' 
    FROM Orders WHERE [email protected] 

    -- this has to be done separately in case orders returns NULL, so no customers are excluded 
    SELECT @CustomerName=CustomerName FROM Customers WHERE [email protected] 

    SELECT @CustomerName as CustomerName, @Orders as Orders 
+1

¿Qué versión de SQL Server hace que ¿tener? – David

+0

SQL Server 2008 – kateroh

Respuesta

9

EDITAR: respuesta modificado para incluir la creación de vista.

/* Set up sample data */ 
create table Customers (
    CustomerId int, 
    CustomerName VARCHAR(100) 
) 

create table Orders (
    CustomerId int, 
    OrderName VARCHAR(100) 
) 

insert into Customers 
    (CustomerId, CustomerName) 
    select 1, 'John' union all 
    select 2, 'Marry' 

insert into Orders 
    (CustomerId, OrderName) 
    select 1, 'New Hat' union all 
    select 1, 'New Book' union all 
    select 1, 'New Phone' 
go 

/* Create the view */  
create view OrderView as  
    select c.CustomerName, x.OrderNames 
     from Customers c 
      cross apply (select stuff((select ',' + OrderName from Orders o where o.CustomerId = c.CustomerId for xml path('')),1,1,'') as OrderNames) x 
go 

/* Demo the view */ 
select * from OrderView 
go 

/* Clean up after demo */ 
drop view OrderView 
drop table Customers 
drop table Orders 
go 
+0

¡Dulce, eso funcionó como magia! Acabo de agregar DISTINCT a la primera declaración de selección y está lista para servir. ¡Gracias! – kateroh

+0

Mmmmm. Marcando este como referencia futura ... :) –

+0

El único problema con mi declaración sql es que no puedes hacer una vista con una declaración indexada como CROSS APPLY no permitida para las vistas indexadas. ¿Alguna sugerencia sobre cómo transformar una vista con esta selección en una vista amigable de índice? ¡Gracias! – kateroh

6

En SQL Server 2008, puede tomar ventaja de algunas de las características añadidas para XML que hacer todo esto en una consulta sin necesidad de utilizar un procedimiento almacenado:

SELECT CustomerName, 
    STUFF(-- "STUFF" deletes the leading ', ' 
     (SELECT ', ' + OrderName 
     FROM Orders 
     WHERE CustomerId = Customers.CutomerId 
     -- This causes the sub-select to be returned as a concatenated string 
     FOR XML PATH('') 
     ), 
    1, 2, '') 
    AS Orders 
FROM Customers 
+0

Dale me gusta David ... utiliza este método XML todo el tiempo para crear cadenas. – scarpacci

+0

Bonito, breve y breve ejemplo: Pude aplicarlo inmediatamente. ¡Aclamaciones! – wloescher

Cuestiones relacionadas