2013-12-12 65 views
0

我在这里有以下工作表,需要转换数据看起来有点不同。为了参数,这里是我正在使用的两个主表。如何更好地编写此查询?

[dbo].[Contracts](
    [ContractId] [int] 
    <Some Other Fields> 
) 

[dbo].[ContractVehicles](
    [ContractVehicleId] [int] 
    [ContractId] [int] **(FK to Contracts)**, 
    [VehicleDescription] [varchar], 
    [Price] [int] 
) 

如您所见,有合同和合同工具。合同可以有许多车辆与之相关联。

我想一个表,如下所示:

[dbo].[ContractSummaries](
    [ContractSummaryId] [int] **(just this table's seed)**, 
    [ContractId] [int] 
    [VehicleType1Desc] [varchar], 
    [VehicleType1Count] [int], 
    [VehicleType1TotalPrice] [int], 
    [VehicleType2Desc] [varchar], 
    [VehicleType2Count] [int], 
    [VehicleType2TotalPrice] [int], 
    [VehicleType3Desc] [varchar], 
    [VehicleType3Count] [int], 
    [VehicleType3TotalPrice] [int] 
) 

基本上,我想列出一份合同,直到与该合同相关联的第3个车型,以#沿表这种类型的车辆,以及该类型的总价格。

为了达到这个目的,我写下了下面的查询。有没有更简洁和有效的方式来写这个? 请注意,我提供的结构或查询都不是实际的查询,我可能在这些表示中出现语法错误。我对此表示歉意,希望这些例子能成功证明我的意图。

SELECT 
    ContractId, 
    (
     SELECT 
      VehicleDescription 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 1 
    ) VehicleType1Desc, 
    (
     SELECT 
      NumVehicle 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 1 
    ) VehicleType1Count, 
    (
     SELECT 
      TotalVehicleTypePrice 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 1 
    ) VehicleType1TotalPrice, 
    (
     SELECT 
      VehicleDescription 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 2 
    ) VehicleType2Desc, 
    (
     SELECT 
      NumVehicle 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 2 
    ) VehicleType2Count, 
    (
     SELECT 
      TotalVehicleTypePrice 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 2 
    ) VehicleType2TotalPrice, 
    (
     SELECT 
      VehicleDescription 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 3 
    ) VehicleType3Desc, 
    (
     SELECT 
      NumVehicle 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 3 
    ) VehicleType3Count, 
    (
     SELECT 
      TotalVehicleTypePrice 
     (
      SELECT 
       ROW_NUMBER() OVER (ORDER BY COUNT(VehicleDescription), ContractId ASC) as rownumber, 
       VehicleDescription, 
       COUNT(v.VehicleDescription) NumVehicle, 
       SUM(Price) TotalVehicleTypePrice 
      FROM 
       Contracts c INNER JOIN ContractVehicles v on c.ContractId = v.ContractId 
      WHERE 
       c.ContractId = cOuter.ContractId 
      GROUP BY 
       v.ContractID, 
       v.VehicleDescription 
     ) countTable 
     WHERE 
      rowNumber = 3 
    ) VehicleType3TotalPrice, 
FROM 
    Contracts outerC 

谢谢!

回答

0

我认为你可以简化查询。以下汇总车辆信息以得到每个合同中每辆车的countprice和“序列号”。然后,将合同信息被加入进来,并把结果汇总:

select c.ContractSummaries, c.ContractSummaryId, 
     max(case when seqnum = 1 then VehicleDescription end) as VehicleType1Desc, 
     max(case when seqnum = 1 then NumV end) as VehicleType1Count, 
     max(case when seqnum = 1 then Price end) as VehicleType1Price, 
     max(case when seqnum = 2 then VehicleDescription end) as VehicleType2Desc, 
     max(case when seqnum = 2 then NumV end) as VehicleType2Count, 
     max(case when seqnum = 2 then Price end) as VehicleType2Price, 
     max(case when seqnum = 3 then VehicleDescription end) as VehicleType3Desc, 
     max(case when seqnum = 3 then NumV end) as VehicleType3Count, 
     max(case when seqnum = 3 then Price end) as VehicleType3Price 
from Contracts c join 
    (select cv.ContractId, cv.VehicleDescription, count(*) as NumV, 
      sum(Price) as Price, 
      row_number() over (partition by ContractId, VehicleDescription 
           order by count(*) desc 
           ) seqnum 
     from ContractVehicles cv 
     group by cv.ContractId, cv.VehicleDescription 
    ) v 
    on c.ContractId = v.ContractId 
group by c.ContractId, c.ContractSummaries, c.ContractSummaryId; 

我在ContractIdContractSummaryId之间的关系尚不清楚 - 你你想要什么的描述是“每张合约的车辆”所以这就是这样做。返回“每个合同摘要中的车辆”的查询可能有点不同。

+0

感谢您的帮助,这让事情变得更加清晰。不知道为什么我决定我需要使用子查询。有一件事我不清楚在你的例子中,是max()在select中的每一列上完成的。在我明天上午把这个转化为实际的查询之后,我一定会把它作为正确的。 –

+0

@DavidGutierrez你也可以使用MIN而不是MAX。这是由于group by子句造成的一个技巧。否则这个查询将不可执行。 –

+0

将row_number()分区调整为不包含车辆描述后,该功能非常有效。再次感谢。 –