2013-05-22 26 views
0

我有一個表,其中包含不同類型的度量,使用id_measure_type來標識它們。我需要做一個SELECT,在該SELECT中我檢索所有期間的總和措施,並且每個單元(id_unit)butif一些措施是空的檢索另一個等等。如果爲空,則按順序檢索不同的值

措施按日期,單位和小時計。這是我的表內容摘要:

 
id_unit  dateBid  hour id_measure_type  measure 
252   05/22/2013 11  6     500 
252   05/22/2013 11  4     250 
252   05/22/2013 11  1     300 
107   05/22/2013 11  4     773 
107   05/22/2013 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所有輸入數據範圍和順序得到「最佳」測量類型:首先是id_measure_type = 6,如果其空或0id_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或失蹤的小時值。我需要每個可能的小時都在「總和」中,從「最好」的可能類型的度量中。

回答

0

Don answer作品完美,但因爲是在表中的大量數據,它持續超過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 
0

我不知道如何你的一些列的是相關的,因爲您提供的每個樣本行具有相同的價值觀,並沒有measure是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 

假設沒有id_measure_type小於0,也沒有measure小於0 - 如果這些都是要求,這些可以適應。

(我添加了一個COALESCE,在你的「空或0」的要求實際上是在談論NULL S和0的假設)

+0

嗯,我的意思是,第二單元上有6類的任何措施,但可能不是很清楚。不會有'NULL'值,只有0個值或缺失值。我的不好,編輯我的問題澄清。 – SysDragon

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]; 

查看輸出的總結之前():

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); 

EDIT(每小時): 我不知道,如果你在表中有更多的數據,上述樣品的總和將只(據我所知)只有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]; 
+0

當有多個不同的小時時不起作用。每個單位只有一個小時,而不是每小時總計最好的度量類型=/ – SysDragon

+0

如果您希望在每個可能的小時內排名等於1,則必須在PARTITION BY中添加小時 – Don

+0

如果度量類型順序不是簡單下降,而是(從最好到最差):'6','1','4'? – SysDragon

相關問題