0

我有一张带有不同类型度量的表格,使用 aid_measure_type来识别它们。我需要做一个 SELECT ,在其中我检索所有该期间和每个单位 ( id_unit) 的度量值,但如果某个度量值是空的,则检索另一个度量值,依此类推。

这些措施是按日期、单位和小时计算的。这是我的表的摘要:

id_unit dateBid hour id_measure_type 测量
252 2013 年 5 月 22 日 11 6 500
252 2013 年 5 月 22 日 11 4 250
252 2013 年 5 月 22 日 11 1 300
107 2013 年 5 月 22 日 11 4 773
107 2013 年 5 月 22 日 11 1 500
24 05/22/2013 11 6 0
24 05/22/2013 11 4 549
24 05/22/2013 11 1 150

我需要一个SUM为所有输入数据范围创建 a 并按以下顺序获取“最佳”度量类型的选择:首先是id_measure_type = 6,如果它为空或 0则为id_measure_type = 4,并且在相同条件下,然后是id_measure_type = 1,如果没有则0。

只要有类型 6 的所有度量,此选择就是正确的:

SELECT id_unit, SUM(measure) AS measure
FROM UNIT_MEASURES
WHERE dateBid BETWEEN '03/23/2013' AND '03/24/2013' AND id_unit IN (325, 326) 
AND id_measure_type = 6 GROUP BY id_unit

输入是日期范围和单位。有一种方法可以在一次选择中完成吗?

编辑:
我还有一个calendar包含每个日期和小时的表,因此如果需要,它可以用来与它进行连接(检索每个小时)。

编辑:
这些值永远不会是NULL,当“空或 0”时,我的意思是 0 或缺失一小时的值。我需要每个可能的小时都在总和中,来自“最佳”可能的度量类型。

4

3 回答 3

1

不确定我是否正确理解您,但我认为这应该可行(更改为您的表格)

我的测试设置:

DECLARE @Table TABLE ([id_unit] INT, [dateBid] DATE, [hour] INT, [id_measure_type] INT, [measure] INT);

INSERT INTO @Table
    SELECT *
      FROM (
        VALUES (252, GETDATE(), 11, 6, 500)
             , (252, GETDATE(), 11, 4, 250)
             , (252, GETDATE(), 11, 1, 300)
             , (107, GETDATE(), 11, 4, 773)
             , (107, GETDATE(), 11, 1, 500)
         ) [Values]([id_unit], [dateBid], [hour], [id_measure_type], [measure]);

实际查询:

WITH [Filter] AS (
    SELECT *
         , DENSE_RANK() OVER(PARTITION BY [id_unit] ORDER BY [id_measure_type] DESC) [Rank]
      FROM @Table
     WHERE [measure] > 0
)
SELECT [id_unit], SUM([measure])
  FROM [Filter]
 WHERE [Rank] = 1
   AND [id_unit] IN (252, 107)
   AND [dateBid] BETWEEN CAST(GETDATE()-1 AS DATE) AND CAST(GETDATE() AS DATE)
 GROUP BY [id_unit];

SUM() 之前的输出视图:

WITH [Filter] AS (
    SELECT *
         , DENSE_RANK() OVER(PARTITION BY [id_unit] ORDER BY [id_measure_type] DESC) [Rank]
      FROM @Table
     WHERE [measure] > 0
)
SELECT *
  FROM [Filter]
 WHERE [Rank] = 1
   AND [id_unit] IN (252, 107)
   AND [dateBid] BETWEEN CAST(GETDATE()-1 AS DATE) AND CAST(GETDATE() AS DATE);

编辑(每小时): 我不知道表中是否有更多数据,对于上面的示例,总和只会(据我所知)只有 SUM() 一行,但它仍然有效,所以我会把它留在里面。

WITH [Filter] AS (
    SELECT *
         , DENSE_RANK() OVER(PARTITION BY [id_unit], [Hour] ORDER BY [id_measure_type] DESC) [Rank]
      FROM @Table
     WHERE [measure] > 0
)
SELECT [id_unit], [Hour], SUM([measure])
  FROM [Filter]
 WHERE [Rank] = 1
   AND [id_unit] IN (252, 107)
   AND [dateBid] BETWEEN CAST(GETDATE()-1 AS DATE) AND CAST(GETDATE() AS DATE)
 GROUP BY [id_unit], [Hour];
于 2013-05-22T09:54:45.840 回答
0

我不确定您的某些列是如何相关的,因为您提供的每个示例行都​​具有相同的值,并且 nomeasure为 0,但我认为您想要的是以下几行:

;With Priorities as (
    select *,ROW_NUMBER() OVER (
         PARTITION BY id_unit,dateBid,hour
         ORDER BY CASE
             WHEN COALESCE(measure,0) > 0 THEN id_measure_type
             else -1 END desc) as priority
    from @t
)
select id_unit,SUM(measure)
from Priorities
where priority = 1
group by id_unit

假设 noid_measure_type小于 0,并且 nomeasure小于 0 - 如果这些是要求,可以调整这些。

(我添加了一个COALESCE,假设您的“空或 0”要求实际上是在谈论NULLs 和 0)

于 2013-05-22T09:40:30.343 回答
0

唐回答完美,但由于表中有很多数据,因此选择持续超过3分钟。

我做了自己的解决方案,它更大更丑,但速度更快(持续约 1 秒):

SELECT tUND.id_unit, ROUND(SUM(
    CASE WHEN ISNULL(t1.measure, 0) > 0 THEN t1.measure ELSE 
    CASE WHEN ISNULL(t2.measure, 0) > 0 THEN t2.measure ELSE
    CASE WHEN ISNULL(t3.measure, 0) > 0 THEN t3.measure ELSE 0 
    END END END END
/1000),3) AS myMeasure
FROM calendar
LEFT OUTER JOIN UNITS_TABLE tUND ON tUND.id_unit IN (252, 107)
LEFT OUTER JOIN MEASURES_TABLE t1 ON t1.id_measure_type = 6 
    AND t1.dateBid = dt AND t1.hour = h AND t1.id_uf = tUND.id_uf
LEFT OUTER JOIN MEASURES_TABLE t2 ON t2.id_unit = t1.id_unit 
    AND t2.dateBid = t1.dateBid AND t2.id_measure_type = 1 
    AND t2.id_unit = tUND.id_unit 
LEFT OUTER JOIN MEASURES_TABLE t3 ON tCNT.id_unit = tUFI.id_unit
    AND t3.dateBid = t1.dateBid AND t3.id_measure_type = 4 
    AND t3.id_unit = tUND.id_unit 
WHERE dt BETWEEN '03/23/2013' AND '03/24/2013' 
GROUP BY tUND.id_unit
于 2013-05-23T10:26:51.357 回答