En utilisant SQL COALESCE en vue
-
28-09-2019 - |
Question
Je dois créer une vue de plusieurs tables. L'une des colonnes de la vue devra être composée d'un nombre de lignes de l'un de la table sous forme de chaîne avec des valeurs séparées par des virgules.
Voici un exemple simplifié de ce que je veux faire.
Customers:
CustomerId int
CustomerName VARCHAR(100)
Orders:
CustomerId int
OrderName VARCHAR(100)
Il y a un à plusieurs entre clients et commandes. Donc, étant donné ces données
Customers
1 'John'
2 'Marry'
Orders
1 'New Hat'
1 'New Book'
1 'New Phone'
Je veux une vue d'être comme ceci:
Name Orders
'John' New Hat, New Book, New Phone
'Marry' NULL
Alors que tout le monde apparaît dans la table, indépendamment du fait qu'ils ont des ordres ou non.
J'ai une procédure stockée que je dois traduire ce point de vue, mais il semble que vous ne pouvez pas déclarer params et appelez procs stockés dans une vue. Toutes les suggestions sur la façon d'obtenir cette requête en vue?
CREATE PROCEDURE getCustomerOrders(@customerId int)
AS
DECLARE @CustomerName varchar(100)
DECLARE @Orders varchar (5000)
SELECT @Orders=COALESCE(@Orders,'') + COALESCE(OrderName,'') + ','
FROM Orders WHERE CustomerId=@customerId
-- this has to be done separately in case orders returns NULL, so no customers are excluded
SELECT @CustomerName=CustomerName FROM Customers WHERE CustomerId=@customerId
SELECT @CustomerName as CustomerName, @Orders as Orders
La solution
EDIT :. Réponse modifiée pour inclure la création de vue
/* 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
Autres conseils
Dans SQL Server 2008, vous pouvez profiter de quelques-unes des fonctionnalités supplémentaires pour XML faire tout cela dans une requête sans utiliser de procédure stockée:
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