I have two tables: Standards and Service Offerings. A Standard can have multiple Service Offerings. Each Standard can have a different number of Service Offerings associated to it.
What I need to be able to do is write a view that will return some common data and then list the service offerings on one line. For example:
Standard Id | Description | SO #1 | SO #2 | SO #3 | ... | SO #21 | SO Count
1 | One | A | B | C | ... | G | 21
2 | Two | A | | | ... | | 1
3 | Three | B | D | E | ... | | 3
I have no idea how to write this. The number of SO columns is set to a specific number (21 in this case), so we cannot exceed past that.
Any ideas on how to approach this?
A place I started is below. It just returned multiple rows for each Service Offering, when they need to be on one row.
SELECT *
FROM SERVICE_OFFERINGS
WHERE STANDARD_KEY IN (SELECT STANDARD_KEY
FROM STANDARDS)
Additional SQL
So here is the SQL I have that returns everything that I want, but will return 11 rows due to there being 11 Service Offerings. I have been trying the pivot table and can't seem to figure it out with this. Can someone help with a code example?
SELECT DISTINCT stpc.standard_key,
stpc.test_id,
NULL AS pricebook_id,
stpc.stabdard_name AS description,
stpc.date_start AS begin_date,
stpc.date_end AS end_date,
sopd.service_offering_id
FROM STANDARDS stpc,
SERVICE_OFFERINGS sopd
WHERE 1=1
AND sopd.standard_key = stpc.standard_key
ORDER BY stpc.standard_key, sopd.service_offering_id
UPDATE
Since the database does not suppose PIVOT tables (and couldn't figure out the XML suggestion), I had to do a little tricky SQL to get it to work. Here is what I used:
select stpc.oracle_product_code AS test_id,
CASE WHEN stpc.store_key = 200 THEN 'CE_USAUSD09'
WHEN stpc.store_key = 210 THEN 'CE_CANCAD09' END AS pricebook_id,
stpc.standard_name AS its_test_desc,
CONVERT(VARCHAR(10), stpc.date_start, 101) AS begin_date,
CONVERT(VARCHAR(10), stpc.date_end, 101) AS end_date,
MAX(CASE WHEN rn = 1 THEN b.service_offering_id END) AS SERVICE_OFFERING_1,
MAX(CASE WHEN rn = 2 THEN b.service_offering_id END) AS SERVICE_OFFERING_2,
MAX(CASE WHEN rn = 3 THEN b.service_offering_id END) AS SERVICE_OFFERING_3,
MAX(CASE WHEN rn = 4 THEN b.service_offering_id END) AS SERVICE_OFFERING_4,
MAX(CASE WHEN rn = 5 THEN b.service_offering_id END) AS SERVICE_OFFERING_5,
MAX(CASE WHEN rn = 6 THEN b.service_offering_id END) AS SERVICE_OFFERING_6,
MAX(CASE WHEN rn = 7 THEN b.service_offering_id END) AS SERVICE_OFFERING_7,
MAX(CASE WHEN rn = 8 THEN b.service_offering_id END) AS SERVICE_OFFERING_8,
MAX(CASE WHEN rn = 9 THEN b.service_offering_id END) AS SERVICE_OFFERING_9,
MAX(CASE WHEN rn = 10 THEN b.service_offering_id END) AS SERVICE_OFFERING_10,
MAX(CASE WHEN rn = 11 THEN b.service_offering_id END) AS SERVICE_OFFERING_11,
MAX(CASE WHEN rn = 12 THEN b.service_offering_id END) AS SERVICE_OFFERING_12,
MAX(CASE WHEN rn = 13 THEN b.service_offering_id END) AS SERVICE_OFFERING_13,
MAX(CASE WHEN rn = 14 THEN b.service_offering_id END) AS SERVICE_OFFERING_14,
MAX(CASE WHEN rn = 15 THEN b.service_offering_id END) AS SERVICE_OFFERING_15,
MAX(CASE WHEN rn = 16 THEN b.service_offering_id END) AS SERVICE_OFFERING_16,
MAX(CASE WHEN rn = 17 THEN b.service_offering_id END) AS SERVICE_OFFERING_17,
MAX(CASE WHEN rn = 18 THEN b.service_offering_id END) AS SERVICE_OFFERING_18,
MAX(CASE WHEN rn = 19 THEN b.service_offering_id END) AS SERVICE_OFFERING_19,
MAX(CASE WHEN rn = 20 THEN b.service_offering_id END) AS SERVICE_OFFERING_20,
MAX(CASE WHEN rn = 21 THEN b.service_offering_id END) AS SERVICE_OFFERING_21,
MAX(rn) AS service_offering_count
FROM (
select standard_key,
service_offering_id,
row_number() over (partition by standard_key order by standard_key) rn
from SERVICE_OFFERINGS
) B,
SERVICE_OFFERINGS sopd,
STANDARDS stpc
where b.service_offering_id = sopd.service_offering_id
AND b.standard_key = stpc.standard_key
AND sopd.standard_key = stpc.standard_key
AND stpc.store_key IN (200,210)
AND stpc.create_date > '03/29/2010'
group by stpc.oracle_product_code,stpc.store_key,stpc.standard_name,stpc.date_start,stpc.date_end
Yep, pivot queries are what you need to use.
Are the 21 column always the same, or is it you can show no more than 21 columns (out of, say, hundreds)? If the actual colmns can vary from query to query, you'll have to look into writing dynamic queries (build the the query as a string--incorporating the columns to be pivoted--and then execute the string).
You can use the PIVOT functionality for this.Check out http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=PIVOTData
Instead of PIVOT, you should use a combination of FOR XML and SplitToColumns.
Use
FOR XML
and pivot out your Offerings to a single column Concatenating Row Values in Transact-SQLThen use a CTE style function to break down a single cell into columns as shown here http://www.sqlservercentral.com/articles/CTE/67974/
This will give you a table pivotted out in the fashion that you need.
Then do arithmetic to get a count of non-null columns and you have the count you need at the end.
Philip is right. If you will always have 21 columns, its a simple Pivot query. I paste here a sample code you could use. But if the number of columns would vary betwenn 1 and 21, you'll have to write a dynamic query.
If the colums may vary yo can try with something like this: