2010-04-01 58 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