MS SQL 2005:子查询

时间:2015-08-06 08:39:18

标签: sql-server sql-server-2005

好的,所以我是SQL菜鸟,而我试图完成这项工作的方式可能不是最好的 - 而且到目前为止它还没有工作,所以这里有:< / p>

我所拥有的是一张充满校准数据的表格。设备由序列号(列串行)标识,每个设备可以具有由RunID标识的多个校准运行。有很多不同的东西需要校准,这些值都存储在CalValue列中。要识别哪一行包含哪种校准,列CalID存在。 我想要得到的是三种不同CalID的CalValue,它们都与某些标准值不同。由于设备可以有多次运行,我只对最近的设备感兴趣。

为了说明:

# Serial    #    RunID    #    CalValue   #    CalID    #
#      1    #        0    #    0.5        #        13   #
#      1    #        0    #    0.8        #        24   #
#      1    #        0    #    0.2        #        35   #
#      1    #        1    #    0.5        #        13   #
#      1    #        1    #    0.3        #        24   #
#      1    #        1    #    0.4        #        35   #
#      1    #        2    #    0.0        #        13   #
#      1    #        2    #   -2.3        #        24   #
#      1    #        2    #    0.6        #        35   #
#      2    #        0    #    0.0        #        13   #
#      2    #        0    #    0.0        #        24   #
#      2    #        0    #    0.0        #        35   #
#      2    #        1    #    0.6        #        13   #
#      2    #        1    #    0.7        #        24   #
#      2    #        1    #    0.8        #        35   #
#      2    #        2    #    0.0        #        13   #
#      2    #        2    #    0.0        #        24   #
#      2    #        2    #    0.0        #        35   #

我理想的想法是:

# Serial    #    CalValue.ID=13    #    CalValue.ID=24   #    CalValue.ID=35    #
#      1    #        0.5           #          0.3        #        0.6           #
#      2    #        0.6           #          0.7        #        0.8           #

选择了Serial 1的值,因为最后所有非默认值都存储在RunID = 1行中。 Serial 2也有多次运行,其中第一次和第三次运行只给出了一些标准值,因此选择了第二次运行的值。

所以我尝试做的是连接表,我过滤掉标准值,然后只选择具有最高RunID的值。我已经尝试了多项内容,最终进入了&#34;列CalValue被多次指定&#34;。如果我的解决方案实际上不起作用,我没有真正的线索,但这是我的方法:

WITH subq3 AS (
SELECT subq0.Serial AS Serial, subq0.RunID AS RunID, subq0.CalValue AS TRth0, subq1.CalValue AS TRth1, subq2.CalValue AS TRth2 
FROM CalibrationData AS subq0
INNER JOIN CalibrationData AS subq1 ON (subq0.Serial = subq1.Serial AND subq0.RunID = subq1.RunID AND ((subq1.CalID=24) AND (subq1.CalValue<>$0.0 And subq1.CalValue<>$0.03))) 
INNER JOIN CalibrationData AS subq2 ON (subq0.Serial = subq2.Serial AND subq0.RunID = subq2.RunID AND ((subq2.CalID=35) AND (subq2.CalValue<>$0.0)))
WHERE ((subq0.CalID=13) AND (subq0.CalValue<>$0.0 And subq0.CalValue<>$-400.0))
)
SELECT t1.Serial, t1.TRth0, t1.TRth1, t1.TRth2
FROM subq3 t1
  LEFT OUTER JOIN subq3 t2
    ON ((t1.Serial = t2.Serial) AND (t1.RunID < t2.RunID))
WHERE t2.Serial IS NULL AND t1.Serial < 90000000
ORDER BY t1.Serial ASC

由于这个问题,我也在SQLFiddle中构建了我的例子,并且它的工作方式正如我想象的那样。所以我的问题实际上是服务器的特定功能。我们有一个MS SQL 2005 Server,它似乎在subq3语句中的别名有问题。

任何建议我如何解决这个问题&#34; CalValue列被多次指定&#34;?

1 个答案:

答案 0 :(得分:1)

更新:添加了业务逻辑

select 
    serial, [13] as [TRth0], [24] as [TRth1],[35] as [TRth2]
from
    (
        select serial,Calvalue,CalID
            from
            (
                select 
                    Serial,
                    Rank() OVER (Partition by Serial order by RunId desc) as rank,
                    calvalue,
                    calid 
                from
                (
                    Select *,count(1) OVER (partition by Serial,runid ) as count from Calibrationdata 
                        where 
                            calValue<>0.00 and 
                                case 
                                    when (calid=13 and calvalue =-400)
                                    or (calid=24 and calvalue =0.03)
                                    then 0 ELSE 1 END =1
                ) d where d.count=3
            ) c
            where c.rank=1
    ) s
PIVOT
( max(calvalue) for calid in ([13],[24],[35])) p

更新了小提琴链接:http://sqlfiddle.com/#!3/c5f52/4

  

我在内部查询中使用了rank()来获取每个serial的最后一次阅读   然后我使用PIVOT来转换输出。

     

请尝试以下查询:

select serial, [13] as [TRth0], [24] as [TRth1],[35] as [TRth2]
from
(
  select 
     serial,Calvalue,CalID
  from
     (
      select 
         Serial, 
         Rank() OVER (Partition by Serial order by RunId desc) as rank, 
         calvalue,
         calid
      from Calibrationdata
      ) c
   where c.rank=1
  ) s
PIVOT
 ( 
   max(calvalue) for calid in ([13],[24],[35])
 ) p
     

sql fiddle link http://sqlfiddle.com/#!3/01c12/7