TSQL in SQL 2005: Query - sql

I have 3 tables: Customer, CustomerTypes, CustomerCustomerTypes. CustomerCustomerTypes is basically is a bridge table between the Customer and CustomerTypes.
Table structure:
Customers:
CustomerID
CustomerName
CustomerTypes:
CustomerTypeID
CusctomerTypeName
CustomerCustomerTypeID
CustomerID
CustomerTypeID
Sample Data:
Customers:
1, ABC
2, CBA
CustomerTypes:
1, Broadcast
2, Banking
3, Retailer
CustomerCustomerTypes:
1, 1
2, 2
2, 3
I want to be able to return query as follow:
ABC; "Broadcasting"
CustomerCustomerTypes; "Banking, Retailer"
as well as to be able to search that string let say "CustomerTypeID = 2"
It will be ruturned as :
CustomerCustomerTypes; "Banking, Retailer"
I can do this with cursor type of query BUT i am just wondering maybe there is a better way.
Thanks

Use:
SELECT c.customername,
STUFF((SELECT ','+ ct.customertypename
FROM CUSTOMERTYPES ct
JOIN CUSTOMERCUSTOMERTYPES cct ON cct.customertypeid = ct.customertypeid
WHERE cct.customerid = C.customerid
GROUP BY ct.customertypename
FOR XML PATH('')), 1, 1, '')
FROM CUSTOMERS c
To be able to search for a specific customer type:
SELECT c.customername,
STUFF(SELECT ','+ ct.customertypename
FROM CUSTOMERTYPES ct
JOIN CUSTOMERCUSTOMERTYPES cct ON cct.customertypeid = ct.customertypeid
WHERE cct.customerid = C.customerid
GROUP BY ct.customertypename
FOR XML PATH(''), 1, 1, '')
FROM CUSTOMERS c
JOIN CUSTOMERCUSTOMERTYPES cct ON cct.customertypeid = ct.customertypeid
WHERE cct.customertypeid = #customertypeid

A SQL Server FOR XML query will give you what you want. I haven't had a chance to check the below but it should point you in the right direction.
SELECT c1.CustomerTypeId,
( SELECT CustomerTypeName + ','
FROM CustomerTypes c2
WHERE c2.CustomerTypeId = c1.CustomerTypeIdId
ORDER BY CustomerTypeName
FOR XML PATH('') ) AS CustomerTypess
FROM CustomerCustomerTypes c1
GROUP BY CustomerTypeId;

Related

SQL - How to Group by and then Concatenate joins?

I have the made a join between 2 tables but the issue is that I need to see unique
CustomerId and concatenate Accreditations with comma separated e,i Gold,Silver,Platinum
Here is my SQL script
SELECT TOP (1000)
Customer.CustomerID,
Customer.CustomerName,
Customer_Accreditations.AccreditationNumber
FROM
Customer INNER JOIN
Customer_Accreditations ON Customer.CustomerID =
Customer_Accreditations.CustomerID
My Result with this script is as follows
CustomerID CustomerName AccreditationNumber
1272 Bree Gold
1272 Bree Gold
1272 Bree Gold
4071 Anneke Silver
4071 Anneke Silver
4071 Anneke Platinum
My desired result should be
CustomerID CustomerName AccreditationNumber
1272 Bree Gold,Gold,Gold
4071 Anneke Silver,Silver,Platinum
So far I have only been able to get unique values and concatenate Accreditations
Here is the script:
SELECT CustomerID, displayname =
STUFF((SELECT DISTINCT ',' + [AccreditationNumber]
FROM Customer_Accreditations b
WHERE b.CustomerID = a.CustomerID
FOR XML PATH('')), 1, 2, '')
FROM [DATABASE_NAME].[dbo].[Customer_Accreditations] a
GROUP BY CustomerID
This returns the following results
______________________________
|CustomerId | displayname |
|____________________________|
|1272 | Gold,Gold,Gold|
______________________________
This is great but if only I could join more of Customer tables/
Many thanks!
Try This
SELECT CustomerID,
CustomerName ,
STUFF(SELECT DISTINCT ', ' + AccreditationNumber
FROM <Table> i
WHERE i.CustomerID = o.CustomerID
FOR XML PATH ('')),1,1,'') AS AccreditationNumber
FROM <Table> o
I think you should be using the customers table to get one row per customer. I think this should be doing what you want:
SELECT c.*,
STUFF( (SELECT ',' + [AccreditationNumber]
FROM Customer_Accreditations ca
WHERE ca.CustomerID = c.CustomerID
FOR XML PATH('')
), 1, 2, ''
) as displayname
FROM [DATABASE_NAME].[dbo].[Customer] c;
SELECT a.CustomerID, a.CustomerName, displayname =
STUFF((SELECT DISTINCT ',' + [AccreditationNumber]
FROM Customer_Accreditations b
WHERE b.CustomerID = a.CustomerID
FOR XML PATH('')), 1, 2, '')
FROM [DATABASE_NAME].[dbo].[Customer] a
GROUP BY a.CustomerID, a.CustomerName

Convert a column of Rows to only one column column in SQL Server query

I have this query in SQL Server 2012 :
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
The result is like this :
id productid
1 1
1 2
1 3
1 10
2 5
2 1
3 4
3 11
but I want this result :
1 1,2,3,10
2 5,1
3 4,11
How can I get that result ?
Try this:
WITH cte as
(
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
)
SELECT id, productid =
STUFF((SELECT ', ' + productid
FROM cte b
WHERE b.id= a.id
FOR XML PATH('')), 1, 2, '')
FROM cte a
GROUP BY id
Use the below query for the desired output.
SELECT tblplantitle.id
, STUFF((SELECT ', ' + CAST(tblplantoproductpayment.productid AS VARCHAR(10)) [text()]
FROM tblplantoproductpayment
WHERE tblplantoproductpayment.planid = tblplan.id
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' ') List_ProductIds
FROM tblplantitle
INNER JOIN tblplan on tblplan.plantitleid = tblplantitle.id
GROUP BY tblplantitle.id

SQL add STUFF function into this query

I have the following query
SELECT TOP 1000
o.BuyerEMail,
COUNT(*) HowMany,
o.Name, o2.OrderID
FROM
Orders o
JOIN
(SELECT
BuyerEmail, MAX(OrderDate) Latest
FROM Orders
GROUP BY BuyerEmail) l ON o.BuyerEmail = l.BuyerEmail
JOIN
Orders o2 ON l.BuyerEmail = o2.BuyerEmail
AND l.OrderDate = o2.OrderDate
WHERE
Pay != 'PayPal'
GROUP BY
o.BuyerEmail, o.Name, l.Latest
ORDER BY
It's just producing a report about customers and how many orders they have with us and the latest order.
What I want to add is a list of the products of their last order which are in lines table.
Lines table is linked to order table by OrderID.
I was looking for something like:
JOIN
(SELECT
OrderID,
STUFF((SELECT ', ' + li.Code
FROM tblLines li
WHERE li.OrderID = o2.OrderID
FOR XML PATH ('')), 1, 1, '') AS [Codes]
GROUP BY
OrderID, Code
So the final table displays as
BuyerEmail | HowMany | Name | Latest | Codes
---------------------------------------------
Bob#bob | 4 | bob | 10000 | 123,10,201231
As you posted the query from another question (SQL most recent order? MS SQL), I will use my answer as it is cleaner than the above query:
SELECT o.*
, OrderID as LastOrderID
FROM (
SELECT BuyerEMail
, Name
, COUNT(*) as TotalOrders
FROM Orders
WHERE Pay != 'PayPal'
GROUP BY BuyerEmail, Name
) o
CROSS APPLY (
SELECT TOP 1 OrderID, OrderDate
FROM Orders s
WHERE s.BuyerEmail = o.BuyerEmail
ORDER BY OrderDate DESC
) ca
You posted a good example, it wasn't complete thou. You would need the following xmlpath query:
SELECT OrderID
, Codes
FROM tblLines r1
CROSS APPLY (
SELECT
STUFF((SELECT ',' + CAST(Code AS NVARCHAR)
FROM tblLines r2
WHERE r2.OrderID = r1.OrderID
GROUP BY OrderID, Code
ORDER BY Code
FOR XML PATH (''), TYPE)
.value('.', 'varchar(max)')
, 1, 1, '')) OrderLines(Codes)
GROUP BY OrderID, OrderList
Add it to the previous statement with a simple join:
SELECT o.BuyerEMail
,o.Name
,o.TotalOrders
, OrderID as LastOrderID
, c.Codes
FROM (
SELECT BuyerEMail
, Name
, COUNT(*) as TotalOrders
FROM Orders
WHERE Pay != 'PayPal'
GROUP BY BuyerEmail, Name
) o
CROSS APPLY (
SELECT TOP 1 OrderID, OrderDate
FROM Orders s
WHERE s.BuyerEmail = o.BuyerEmail
ORDER BY OrderDate DESC
) ca
INNER JOIN (
SELECT OrderID
, Codes
FROM tblLines r1
CROSS APPLY (
SELECT
STUFF((SELECT ',' + CAST(Code AS NVARCHAR)
FROM tblLines r2
WHERE r2.OrderID = r1.OrderID
GROUP BY OrderID, Code
ORDER BY Code
FOR XML PATH (''), TYPE)
.value('.', 'varchar(max)')
, 1, 1, '')) OrderLines(Codes)
GROUP BY OrderID, OrderList
) c
ON ca.OrderID = c.OrderID
SELECT TOP 1000
o.BuyerEMail,
COUNT(*) HowMany,
o.Name, l.Latest,
STUFF((SELECT ', ' + li.Code
FROM tblLines li
WHERE li.OrderID = o2.OrderID
FOR XML PATH ('')), 1, 1, '') AS [Codes]
FROM
Orders o
JOIN
(SELECT
BuyerEmail, MAX(OrderDate) Latest
FROM Orders
GROUP BY BuyerEmail) l ON o.BuyerEmail = l.BuyerEmail
JOIN
Orders o2 ON l.BuyerEmail = o2.BuyerEmail
AND l.OrderDate = o2.OrderDate
WHERE
Pay != 'PayPal'
GROUP BY
o.BuyerEmail, o.Name, l.Latest
ORDER BY

how to select and print from each variable in another select sql query

I use this query and get a list of company names in many rows (each name in one row)
select distinct companyName from Companies
from each name I can use this query to get another property related to that company name:
SELECT distinct
STUFF((SELECT ', '+ cn.name
from WMCCMCategories cn
INNER JOIN CategorySets uc
ON uc.categoryId = cn.categoryID
INNER JOIN KeyProcesses u
ON u.categorySetId = uc.setId
INNER JOIN Companies c
ON c.companyId = u.companyId
WHERE c.companyName = #companyName
ORDER BY cn.name FOR XML PATH('')), 1, 1, '') AS listStr
FROM WMCCMCategories cnn
Group by cnn.name
Now, I want to apply that query for each name in the first query, so I replace #companyName by that first query:
SELECT distinct
STUFF((SELECT ', '+ cn.name
from WMCCMCategories cn
INNER JOIN CategorySets uc ON uc.categoryId = cn.categoryID
INNER JOIN KeyProcesses u ON u.categorySetId = uc.setId
INNER JOIN Companies c ON c.companyId = u.companyId
WHERE c.companyName in
(select distinct companyName from Companies)
ORDER BY cn.name FOR XML PATH('')), 1, 1, '') AS listStr
FROM
WMCCMCategories cnn
GROUP BY
cnn.name
But it will print all the results in one row. What I need is the result for each company names in one rows, and I can get each properties for each company Names. How could I modify to get that ?
Write as:
SELECT distinct
c1.companyName,
STUFF((SELECT ', '+ cn.name
from WMCCMCategories cn
INNER JOIN CategorySets uc
ON uc.categoryId = cn.categoryID
INNER JOIN KeyProcesses u
ON u.categorySetId = uc.setId
INNER JOIN Companies c
ON c.companyId = u.companyId
WHERE c.companyName = c1.companyName
ORDER BY cn.name FOR XML PATH('')), 1, 1, '') AS listStr
FROM Companies c1
Group by c1.companyName

SQL: Combining Rows with Some Conditions And Delete Rest of Them

I have a table like this;
Table: PROSPECT
ID CUSTOMER NUMBER
1 A XXXA1
1 B XXXA1
1 G XXX00
2 C XXX32
2 D XXX32
2 E XXX32
2 F XXX66
I want to combine rows' customer's name with ; where they has same ID and NUMBER. (and delete other rows.)
I want to it like this;
Table: PROSPECT
ID CUSTOMER NUMBER
1 A;B XXXA1
1 G XXX00
2 C;D;E XXX32
2 F XXX66
How can I do that?
Disclaimer
I agree with #Dems that you should not change your normalized data to this.
A better alternative might be to create a VIEW that presents you the data in the format you need.
SQL Statement
CREATE VIEW dbo.VIEW_PROSPECT AS
SELECT po.ID
, STUFF((SELECT '; ' + CUSTOMER FROM PROSPECT pi WHERE pi.ID = po.ID AND pi.N UMBER = po.NUMBER ORDER BY CUSTOMER FOR XML PATH('')),1,2,'') AS CUSTOMER
, po.NUMBER
FROM PROSPECT po
GROUP BY
po.ID
, po.NUMBER
Test script
;WITH PROSPECT(ID, CUSTOMER, NUMBER) AS (
SELECT 1, 'A', 'XXXA1'
UNION ALL SELECT 1, 'B', 'XXXA1'
UNION ALL SELECT 1, 'G', 'XXX00'
UNION ALL SELECT 2, 'C', 'XXX32'
UNION ALL SELECT 2, 'D', 'XXX32'
UNION ALL SELECT 2, 'E', 'XXX32'
UNION ALL SELECT 2, 'F', 'XXX66'
)
SELECT po.ID
, STUFF((SELECT '; ' + CUSTOMER FROM PROSPECT pi WHERE pi.ID = po.ID AND pi.NUMBER = po.NUMBER ORDER BY CUSTOMER FOR XML PATH('')),1,2,'') AS CUSTOMER
, po.NUMBER
FROM PROSPECT po
GROUP BY
po.ID
, po.NUMBER
ORDER BY
ID
, CUSTOMER
, NUMBER
SELECT DISTINCT ID, LEFT(T.CUSTOMER,LEN(T.CUSTOMER)-1), NUMBER
FROM PROSPECT A CROSS APPLY
(SELECT CUSTOMER + ';' AS [text()] FROM PROSPECT B
WHERE A.ID = B.ID and A.NUMBER = B.NUMBER
ORDER BY ID FOR XML PATH('')) T (CUSTOMER)