2010-04-01 73 views
2

我在MS SQL Server中有一個複雜的SQL問題,並且在繪製一張紙時,我意識到我可以將其視爲一個填充矩形的單條,每個矩形都有段具有不同的Z指令。實際上,它與z順序或圖形完全無關,但更多的是與一些難以解釋的複雜業務規則相關。不管怎樣,如果有人對如何解決下面的問題有想法,那會給我解決方案。複雜的SQL查詢類似於AZ訂單問題

,我有以下數據:

ObjectID | PercentOfBar | ZOrder (where smaller is closer) 
--------------------------------------------------------------- 
A   | 100   | 6 
B   | 50   | 5 
B   | 50   | 4 
C   | 30   | 3 
C   | 70   | 6 

,我想是這樣的,以任何順序我查詢的結果:

PercentOfBar | ZOrder 
------------------------- 
50   | 5 
20   | 4 
30   | 3 

認爲它是這樣的,如果我畫矩形A ,它會填滿100%的酒吧,並有AZ的順序6.

6666666666 
AAAAAAAAAA 

如果我然後奠定了長方形B,由兩個s egments,這兩個領域將掩蓋矩形A導致以下渲染:

4444455555 
BBBBBBBBBB 

作爲一個經驗法則,對於給定的矩形,這是段應奠定了這樣的最高Z順序是正確的低Z指令。

最後,矩形C只會掩蓋矩形B的一部分,它的30%分段是z階3,它將在左邊。你可以希望看到的是在輸出數據集我上面列出表示:

3334455555 
CCCBBBBBBB 

現在使事情變得更加複雜我其實有4列,使得該組出現的每個關鍵:

輸入:

SomeKey, ObjectID, PercentOfBar, ZOrder (where smaller is closer) 
X, A, 100, 6 
X, B, 50, 5 
X, B, 50, 4 
X, C, 30, 3 
X, C, 70, 6 
Y, A, 100, 6 
Z, B, 50, 2 
Z, B, 50, 6 
Z, C, 100, 5 

輸出:在輸出中,噸

SomeKey, PercentOfBar, ZOrder 
X, 50, 5 
X, 20, 4 
X, 30, 3 
Y, 100, 6 
Z, 50, 2 
Z, 50, 5 

通知每個SomeKey的PercentOfBar會加起來達到100%。

這是一個我知道我會考慮什麼時候我今晚睡覺的時候。

只要是明確的,有一個問題:

什麼是會產生上述結果的查詢?

+1

AaronLS,請查看我的修訂,以您的題。我從6行和A行中刪除了「6」和「A」,所以現在每行有10行。這是你的意圖嗎?如果不是,請將其回滾(或更正)。 – devuxer 2010-04-01 00:59:52

+1

Is(SomeKey,ObjectID,ZOrder)是否唯一?如果沒有,你的桌子上是否有PK或其他獨特的索引? – 2010-04-01 10:29:08

+0

@DanM Perfect Thanks – AaronLS 2010-04-01 19:36:20

回答

1

我做如下假設:

  • 您使用SQL Server 2005或更高版本。
  • SomeKey,ObjectID,ZOrder是唯一的。

其他說明:

  • 我沒有優化的查詢 - 我只是試圖得到正確的結果。
  • 我只在測試數據上測試過它。

考慮到這一點,你可以嘗試這樣的事:

WITH Bars AS (
    SELECT 
     T1.SomeKey, 
     T1.ObjectID, 
     T1.ZOrder, 
     SUM(T2.PercentOfBar) - T1.PercentOfBar AS PercentStart, 
     SUM(T2.PercentOfBar) AS PercentEnd 
    FROM Table1 T1 
    JOIN Table1 T2 
    ON T1.SomeKey = T2.SomeKey 
     AND T1.ObjectID = T2.ObjectID 
     AND T1.ZOrder >= T2.ZOrder 
    GROUP BY T1.SomeKey, T1.ObjectID, T1.PercentOfBar, T1.ZOrder), 
Boundaries AS (
    SELECT P, ROW_NUMBER() OVER (ORDER BY P) AS rn 
    FROM (
     SELECT DISTINCT PercentStart AS P FROM Bars 
     UNION 
     SELECT DISTINCT PercentEnd FROM Bars 
    ) T1), 
Intervals AS (
    SELECT B1.P AS PercentStart, B2.P AS PercentEnd 
    FROM Boundaries B1 
    JOIN Boundaries B2 
     ON B1.rn + 1 = B2.rn), 
Bits AS (
    SELECT 
     SomeKey, 
     ObjectId, 
     ZOrder, 
     Intervals.PercentStart, 
     Intervals.PercentEnd 
    FROM Intervals 
    JOIN Bars 
     ON Bars.PercentStart <= Intervals.PercentStart 
     AND Bars.PercentEnd >= Intervals.PercentEnd), 
LowestZOrder AS (
    SELECT SomeKey, PercentStart, MIN(ZOrder) AS ZOrder 
    FROM Bits 
    GROUP BY SomeKey, PercentStart), 
LowestBits AS (
    SELECT Bits.* 
    FROM Bits 
    JOIN LowestZOrder 
     ON Bits.SomeKey = LowestZOrder.SomeKey 
     AND Bits.PercentStart = LowestZOrder.PercentStart 
     AND Bits.ZOrder = LowestZOrder.ZOrder) 
SELECT 
    SomeKey, 
    MAX(PercentEnd) - MIN(PercentStart) AS PercentOfBar, 
    ZOrder 
FROM LowestBits 
GROUP BY SomeKey, ObjectID, ZOrder 
ORDER BY SomeKey, ObjectID, MIN(PercentStart) DESC 

結果:

SomeKey PercentOfBar ZOrder 
X  50   5 
X  20   4 
X  30   3 
Y  100   6 
Z  50   2 
Z  50   5 

測試數據:

CREATE TABLE Table1 (SomeKey NVARCHAR(100) NOT NULL, ObjectID NVARCHAR(100) NOT NULL, PercentOfBar INT NOT NULL, ZOrder INT NOT NULL); 
INSERT INTO Table1 (SomeKey, ObjectID, PercentOfBar, ZOrder) VALUES 
('X', 'A', 100, 6), 
('X', 'B', 50, 5), 
('X', 'B', 50, 4), 
('X', 'C', 30, 3), 
('X', 'C', 70, 6), 
('Y', 'A', 100, 6), 
('Z', 'B', 50, 2), 
('Z', 'B', 50, 6), 
('Z', 'C', 100, 5); 
+0

+!除了2000兼容模式數據庫外,您的假設是正確的,但通常我可以通過運行2005兼容模式數據庫中的查詢並使用3部分命名約定來定位2000數據庫中的表來解決此問題。 – AaronLS 2010-04-01 20:36:19