views:

53

answers:

3

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
+2  A: 
Raj More
+1  A: 

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).

Philip Kelley
+1  A: 

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.

SELECT standard_key, stabdard_name, [A] as SO1, [B] as SO2, [C] as SO3, [D] as SO4, [E] as SO5....-- and so on with the other columns
FROM 
(SELECT ST.standard_key, ST.stabdard_name, SO.service_offering_id
FROM SERVICE_OFFERINGS SO
    INNER JOIN STANDARDS ST
        ON SO.standard_key= ST.standard_key)p
PIVOT
(
MAX (service_offering_id)
FOR service_offering_id IN
( [A], [B], [C], [D], [E]....-- and so on with the other values)
) AS pvt
ORDER BY standard_key

If the colums may vary yo can try with something like this:

declare @sql nvarchar(max)
declare @sql2 nvarchar(max)

SET @sql2=''
set @sql = '
select
    standard_key, stabdard_name,'

select @sql = @sql + '['+ service_offering_id + '] AS [SO' +  convert(varchar, Row_number() OVER (ORDER BY  service_offering_id))+ '],'
from (select distinct [service_offering_id] from [SERVICE_OFFERINGS]) as moduleids

select @sql2 = @sql2 + '['+ service_offering_id + '],'
from (select distinct [service_offering_id] from [SERVICE_OFFERINGS]) as moduleids

set @sql2 = substring(@sql2,1,len(@sql2)-1)

set @sql = substring(@sql,1,len(@sql)-1) + '
FROM 
(SELECT ST.standard_key, ST.stabdard_name, SO.service_offering_id
FROM SERVICE_OFFERINGS SO
    INNER JOIN STANDARDS ST
        ON SO.standard_key= ST.standard_key)p
PIVOT
(
MAX (service_offering_id)
FOR service_offering_id IN
(' + @sql2 + 
')) AS pvt
ORDER BY standard_key'

print @sql

exec sp_executesql @sql
Claudia
Thank you so very much for the example. I tried running that and apparently I need to update the compatibility level of the database. Once that is done, I will definitely check this out. Thanks!
Ascalonian