SQL Server Splitting colum of a table into two columns while joining to other table

h9a6wy2h  于 2023-03-11  发布在  其他
关注(0)|答案(2)|浏览(133)

I got two tables:

t1:

Reference # Reference   TypeId
25253       1       60
30765       1       60
30765       3       61
33061       1       61
34037       6       60
35532       5       60
35750       1       60
35750       2       61
35750       4       61
35860       6       60
35860       2       61
35909       4       60
35936       5       60
35936       2       61
35965       1       61
36080       4       60
36080       2       61
36080       4       61

t2:

Id  TypeId  Reference   Description
360 60       1               Studio
361 60       2               1 bedroom
362 60       3               2 bedroom
363 60       4               3 bedroom
364 60       5               4 bedroom
365 60       6               5 bedroom
366 60       7               6 bedroom
367 61       1               Zone 1 - East
368 61       2               Zone 2 - South
369 61       3               Zone 3 - Central
370 61       4               Zone 4 - West
371 61       5               Zone 5 - North

I want to bring in 'Description' column from t2 into t1 in such a way that description column split into two columns based on TypeId value. I wrote following query to join the tables:

Select t1.Reference#, t1.reference,t1.TypeId, 
Case when t1.TypeId = 60 then t2.description end as 'No of Bedrooms'
Case when t1.TypeId = 61 then t2.description end as 'Zone'
from t1 
join t2 on t1.TypeId = t2.TypeId and t1.reference = t2.reference

Above lines produced following output:

Result:

Reference#  Reference   TypeId  No of Bedrooms  Zone
25253          1           60   Studio           NULL
30765          1           60   Studio           NULL
30765          3           61   NULL             Zone 3 - Central
33061          1           61   NULL             Zone 1 - East
34037          6           60   5 bedroom        NULL
35532          5           60   4 bedroom        NULL
35750          1           60   Studio           NULL
35750          2           61   NULL             Zone 2 - South
35750          4           61   NULL             Zone 4 - West
35860          6           60   5 bedroom        NULL
35860          2           61   NULL             Zone 2 - South
35909          4           60   3 bedroom        NULL
35936          5           60   4 bedroom        NULL
35936          2           61   NULL             Zone 2 - South
35965          1           61   NULL             Zone 1 - East
36080          4           60   3 bedroom        NULL
36080          2           61   NULL             Zone 2 - South
36080          4           61   NULL             Zone 4 - West

The problem with above output is that it shows either value of 'No of Bedrooms' or 'Zone' in a row. It wont show both values in the same row. My desired output looks like as follow:

Desired output:

Not sure simple join would work for the desired output. Any help would be appreciated to get the desired output.

oyxsuwqo

oyxsuwqo1#

How about:

;With JoinedData as (
    Select t1.ReferenceNo, t2.TypeId, t2.Reference, t2.Description
    from t1
    join t2 on t2.TypeId = t1.TypeId and t2.Reference = t1.Reference
)
Select
    COALESCE(t60.ReferenceNo, t61.ReferenceNo) as ReferenceNo,
    t60.Reference as NoOfBedroomsReference,
    t61.Reference as ZoneReference,
    t60.Description as NoOfBedrooms,
    t61.Description as Zone
  
from (
    Select *
    from JoinedData
    where TypeId = 60
) t60
full outer join (
    Select *
    from JoinedData
    where TypeId = 61
) t61
    on t61.ReferenceNo = t60.ReferenceNo
order by ReferenceNo, t60.Reference, t61.Reference

The same without using a CTE (Common Table Expression):

Select
    COALESCE(t60.ReferenceNo, t61.ReferenceNo) as ReferenceNo,
    t60.Reference as NoOfBedroomsReference,
    t61.Reference as ZoneReference,
    t60.Description as NoOfBedrooms,
    t61.Description as Zone
from (
    Select t1.ReferenceNo, t2.TypeId, t2.Reference, t2.Description
    from t1
    join t2 on t2.TypeId = t1.TypeId and t2.Reference = t1.Reference
    where t1.TypeId = 60
) t60
full outer join (
    Select t1.ReferenceNo, t2.TypeId, t2.Reference, t2.Description
    from t1
    join t2 on t2.TypeId = t1.TypeId and t2.Reference = t1.Reference
    where t1.TypeId = 61
) t61
    on t61.ReferenceNo = t60.ReferenceNo
order by ReferenceNo, t60.Reference, t61.Reference

For each ReferenceNo, this takes every number-of-bedrooms attribute value and cross joins it to every Zone attribute value.

Results:
| ReferenceNo | NoOfBedroomsReference | ZoneReference | NoOfBedrooms | Zone |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| 25253 | 1 | null | Studio | null |
| 30765 | 1 | 3 | Studio | Zone 3 - Central |
| 33061 | null | 1 | null | Zone 1 - East |
| 34037 | 6 | null | 5 bedroom | null |
| 35532 | 5 | null | 4 bedroom | null |
| 35750 | 1 | 2 | Studio | Zone 2 - South |
| 35750 | 1 | 4 | Studio | Zone 4 - West |
| 35860 | 6 | 2 | 5 bedroom | Zone 2 - South |
| 35909 | 4 | null | 3 bedroom | null |
| 35936 | 5 | 2 | 4 bedroom | Zone 2 - South |
| 35965 | null | 1 | null | Zone 1 - East |
| 36080 | 4 | 2 | 3 bedroom | Zone 2 - South |
| 36080 | 4 | 4 | 3 bedroom | Zone 4 - West |

Only the 35750 and 36080 ReferenceNo values are repeated, because they have multiple values for the same attribute.

See this db<>fiddle for a working demo.

vmdwslir

vmdwslir2#

You could use window functions with your query as the following:

SELECT t1.Reference#, 
       t1.reference,
       t1.TypeId, 
       MAX(CASE WHEN t1.TypeId = 60 THEN t2.description END) OVER (PARTITION BY t1.Reference#) AS [No of Bedrooms],
       CASE
        WHEN t1.TypeId = 60 AND COUNT(CASE WHEN t1.TypeId = 61 THEN 1 END) OVER (PARTITION BY t1.Reference#) = 1
         THEN MAX(CASE WHEN t1.TypeId = 61 THEN t2.description END) OVER (PARTITION BY t1.Reference#)
        WHEN t1.TypeId = 61 
         THEN t2.description
       END AS [Zone]
FROM table1 t1 JOIN table2 t2 
  ON t1.TypeId = t2.TypeId AND t1.reference = t2.reference
ORDER BY t1.Reference#, t1.TypeId, t1.reference

See demo

相关问题