在单行中获取数据

时间:2011-09-22 13:52:05

标签: sql sql-server sql-server-2008

我有两个表PackageDetail和PackageDuration PackageDuration将PackageID作为外键,即可以有多个与PackageID相关的记录

PackageDetail的架构是:

PackageID  INT PK
PackageName Nvarchar(50)

PackageDuration表的架构是:

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

PackageDetail表有以下记录:

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不超过这个(如果忽略的话) 现在我想按照以下方式选择记录:

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

请建议我如何实现这个目标。

4 个答案:

答案 0 :(得分: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

答案 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

答案 2 :(得分: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;

答案 3 :(得分:0)

也许我在需求中遗漏了一些东西,但看起来Sql Server的PIVOT就是您正在寻找的东西。

有关于PIVOT的quite a few questions here at SO ...这是一个很好的例子,其中提到了其他问题:How do i transform rows into columns in sql server 2005

数据透视表相对于其他答案的一大好处是,如果您将来向PackageDuration表添加记录,它将无需修改即可扩展。