我在MS SQL Server中遇到了一个复杂的SQL问题,在一张纸上绘图时,我意识到我可以把它想象成一个填充了矩形的单个条形图,每个矩形都有不同Z顺序的分段。实际上它根本与z顺序或图形无关,而更多地与一些难以解释的复杂业务规则有关。无论如何,如果有人有关于如何解决下面的想法,那将给我解决方案。
我有以下数据:
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%的条形并且z顺序为6。
6666666666
AAAAAAAAAA
如果我然后布置由两个段组成的矩形B,则两个段都将覆盖矩形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%。
我知道这是我今晚睡觉时会想到的。
只是要明确并提出问题:
会产生上述结果的查询是什么?
答案 0 :(得分:1)
我做了以下假设:
其他说明:
考虑到这一点你可以尝试这样的事情:
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);