2011-09-22 44 views
1

我有两个表PackageDetail和PackageDuration PackageDuration有包标识为外键即可以具有的与多个记录包标识获取数据

的PackageDetail的模式是:

PackageID INT PK 
PackageName Nvarchar(50) 
在PackageDuration表

模式是:

DurationID INT PK 
Price Money 
Duration Nvarchar(50) 
PackageID INT FPK 

PackageDetail表有follwoing记录:

PackageID  PackageName 
    1    TestPackage 
    2    MySecondPackage 

PackageDuration表有以下记录:

DurationID  PackageID Price  Duration 
    1     1  100   6 
    2     1  200   12 
    3     1  300   24 
    4     2  500   6 

PackageDuration表可以有最多3条记录与一个包标识不比这更多的(如果有忽略) 现在我要选择的记录作为以下方式:

PackageId PackageNAme  Price1 Price2 Price3 Duration1 Duration2 Duration3 
1   TestPackage  100 200 300   6   12   24 
2   MySecondPackage 500 null null   6  null   null 

请建议我如何完成此操作。

+0

如果PackageID 1有4个价格怎么办?您是否需要为Price4和Duration4动态添加列? –

+0

是的,一个套餐可以根据持续时间6月,12(1年),24(2年)最大3价格 – Askiitians

回答

5

另一种方法:

WITH Durations AS 
(
    SELECT *, ROW_NUMBER() OVER(PARTITION BY PackageId ORDER BY DurationId) Sequence 
    FROM PackageDuration 
) 

SELECT A.PackageId, B.PackageName, 
     MIN(CASE WHEN Sequence = 1 THEN Price ELSE NULL END) Price1, 
     MIN(CASE WHEN Sequence = 2 THEN Price ELSE NULL END) Price2, 
     MIN(CASE WHEN Sequence = 3 THEN Price ELSE NULL END) Price3, 
     MIN(CASE WHEN Sequence = 1 THEN Duration ELSE NULL END) Duration1, 
     MIN(CASE WHEN Sequence = 2 THEN Duration ELSE NULL END) Duration2, 
     MIN(CASE WHEN Sequence = 3 THEN Duration ELSE NULL END) Duration3 
FROM Durations A 
INNER JOIN PackageDetail B 
ON A.PackageId = B.PackageId 
GROUP BY A.PackageId, B.PackageName 
+0

+1我最喜欢这个,因为没有硬编码值。你知道,(需求)常量可能会随时间而改变......从现在开始一年:“你知道,我们应该改变持续时间值,那些定义在哪里?” –

1

这应该工作,只要持续时间是一个包独特的,他们要么是6,12,或24

SELECT 
    PackageDetail.PackageId, PackageDetail.PackageName, 
    D1.Price as Price1, D2.Price as Price2, D3.Price as Price3, 
    D1.Duration as Duration1, D2.Duration as Duration2, D3.Duration as Duration3 
FROM PackageDetail 
LEFT OUTER JOIN PackageDuration D1 
    ON D1.PackageId = PackageDetail.PackageId AND D1.Duration = 6 
LEFT OUTER JOIN PackageDuration D2 
    ON D2.PackageId = PackageDetail.PackageId AND D2.Duration = 12 
LEFT OUTER JOIN PackageDuration D3 
    ON D3.PackageId = PackageDetail.PackageId AND D3.Duration = 24 
0
;WITH pvt AS 
(
    SELECT PackageID, 
     Price1 = MAX(CASE WHEN Duration = 6 THEN Price END), 
     Price2 = MAX(CASE WHEN Duration = 12 THEN Price END), 
     Price3 = MAX(CASE WHEN Duration = 24 THEN Price END), 
     Duration1 = MAX(CASE WHEN Duration = 6 THEN 6 END), 
     Duration2 = MAX(CASE WHEN Duration = 12 THEN 12 END), 
     Duration3 = MAX(CASE WHEN Duration = 24 THEN 24 END) 
    FROM dbo.PackageDuration 
    GROUP BY PackageID 
) 
SELECT 
    pvt.PackageID, 
    p.PackageName, 
    pvt.Price1, pvt.Price2, pvt.Price3, 
    pvt.Duration1, pvt.Duration2, pvt.Duration3 
FROM 
    dbo.PackageDetail AS p 
INNER JOIN 
    pvt ON p.PackageID = pvt.PackageID 
ORDER BY p.PackageID; 
0

也许我在需求中缺少一些东西,但它似乎像Sql Server的PIVOT是你正在寻找的东西。

quite a few questions here at SO约PIVOT ...以下是与其他问题时引用了良好清晰的例子:How do i transform rows into columns in sql server 2005

在这里其他的答案透视表的一大好处是,它会向外扩展,没有修改,如果您将记录添加到您未来的PackageDuration表中。

+0

我开始在使用PIVOT的解决方案上工作,但有一些问题需要输出,这会使PIVOT比必要更复杂。如果只需要前4列,使用PIVOT编写将会更加直观。 –