我有3个表代表关系/层次结构的表:
A.ID
B.AID
C.BID
DDL和sqlfiddle :(在实际数据库中有更多列)
CREATE TABLE A
([ID] int, [Title] varchar(50), [Sort] int)
;
INSERT INTO A
([ID], [Title], [Sort])
VALUES
(5, 'a5', 1),
(4, 'a4', 2),
(7, 'a7', 3)
;
CREATE TABLE B
([ID] int, [AID] int, [Title] varchar(50), [Sort] int)
;
INSERT INTO B
([ID], [AID], [Title], [Sort])
VALUES
(2, 5, 'b2', 1), -- a5
(3, 5, 'b3', 2),
(8, 4, 'b8', 1), -- a4
(4, 7, 'b4', 1), -- a7
(6, 7, 'b6', 2),
(5, 7, 'b5', 3)
;
CREATE TABLE C
([ID] int, [BID] int, [Title] varchar(50), [Sort] int)
;
INSERT INTO C
([ID], [BID], [Title], [Sort])
VALUES
(1, 2, 'c1', 1), -- b2
(8, 2, 'c8', 2),
(2, 3, 'c2', 1), -- b3
(3, 8, 'c3', 1), -- b8
(7, 4, 'c7', 1), -- b4
(4, 6, 'c4', 1), -- b6
(6, 5, 'c6', 1), -- b5
(5, 5, 'c5', 2)
;
我需要获得一个按表关系分组的结果集,但顺序是由每个组的Sort
列确定的(分区?)。
我用过:
SELECT * FROM
A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
ORDER BY A.Sort, B.Sort, C.Sort;
获得所需结果:
ID Title Sort ID AID Title Sort ID BID Title Sort
5 a5 1 2 5 b2 1 1 2 c1 1
5 a5 1 2 5 b2 1 8 2 c8 2
5 a5 1 3 5 b3 2 2 3 c2 1
4 a4 2 8 4 b8 1 3 8 c3 1
7 a7 3 4 7 b4 1 7 4 c7 1
7 a7 3 6 7 b6 2 4 6 c4 1
7 a7 3 5 7 b5 3 6 5 c6 1
7 a7 3 5 7 b5 3 5 5 c5 2
或包含Sort
列的层次结构视图:
a5 (1)
|__
b2 (1)
|__
c1 (1)
c8 (2)
b3 (2)
|__
c2 (1)
a4 (2)
|__
b8 (1)
|__
c3 (1)
a7 (3)
|__
b4 (1)
|__
c7 (1)
b6 (2)
|__
c4 (1)
b5 (3)
|__
c6 (1)
c5 (2)
当Sort
值未“标准化”时,问题就开始了。当a5
和a7
Sort
== 1(相同的值)时,例如。或者当所有A.Sort
值都设置为0时(表B
和C
也是如此)。
注意:“未规范化”是指每个表中的Sort
值可以是任意数。 e.g。
UPDATE A SET Sort = 0;
看到分组中断(a7
),我得到随机结果:
ID Title Sort ID AID Title Sort ID BID Title Sort
4 a4 0 8 4 b8 1 3 8 c3 1
7 a7 0 4 7 b4 1 7 4 c7 1 <-- a7
5 a5 0 2 5 b2 1 1 2 c1 1
5 a5 0 2 5 b2 1 8 2 c8 2
5 a5 0 3 5 b3 2 2 3 c2 1
7 a7 0 6 7 b6 2 4 6 c4 1 <-- a7
7 a7 0 5 7 b5 3 6 5 c6 1
7 a7 0 5 7 b5 3 5 5 c5 2
我想尽最大努力让Sort
订单正确,但保持分组/层次结构正确。怎么办呢?
我也尝试过:
ORDER BY
A.Sort, A.ID,
B.Sort, B.ID,
C.Sort, C.ID;
似乎有效。但不知何故,这对我来说并不合适。 我几乎可以肯定解决方案是类似
ROW_NUMBER() OVER(PARTITION BY A.ID, B.ID, C.ID ORDER BY A.Sort, B.Sort, C.Sort)
但我无法得到正确的结果。
编辑#1 :我认为这应该有效,但我仍然需要测试,因为我不确定:
SELECT
ROW_NUMBER() OVER(ORDER BY A.Sort) s1,
ROW_NUMBER() OVER(PARTITION BY A.ID ORDER BY B.Sort) s2,
ROW_NUMBER() OVER(PARTITION BY B.ID ORDER BY C.Sort) s3,
*
FROM
A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
ORDER by s1, s2, s3
编辑#2 :编辑后,编辑#1没有按预期工作。 似乎工作的唯一方法就是简单:
ORDER BY A.Sort, A.ID,
B.Sort, B.ID,
C.Sort, C.ID; -- actually the C.ID is not needed
答案 0 :(得分:0)
试试这个
SELECT * FROM
A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
ORDER BY CASE WHEN A.Sort = 0 THEN A.ID ELSE A.Sort END,
CASE WHEN B.Sort = 0 THEN B.ID ELSE B.Sort END,
CASE WHEN C.Sort = 0 THEN C.ID ELSE C.Sort END
编辑随机数 - 请尝试以下
SELECT *,DENSE_RANK() OVER (ORDER BY A.ID,A.Sort) AS RNK1
,DENSE_RANK() OVER (ORDER BY B.ID,B.Sort) AS RNK2
,DENSE_RANK() OVER (ORDER BY C.ID,C.Sort) AS RNK3
FROM
A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
ORDER BY RNK1,RNK2,RNK3
答案 1 :(得分:0)
如果它只是你要保留的'分组',你可以通过id或title的条件排序来完成这个,如下所示:
SELECT *
FROM A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
ORDER BY CASE WHEN A.Sort = 0 THEN A.ID ELSE A.Sort END,
CASE WHEN B.Sort = 0 THEN B.ID ELSE B.Sort END,
CASE WHEN C.Sort = 0 THEN C.ID ELSE C.Sort END;
这样,如果排序值为零,它将仅按id排序。 您还可以通过子查询获取MAX和MIN排序值,并检查它们是否相等。
更新:MAX / MIN聚合示例:
SELECT *
FROM A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
LEFT JOIN (SELECT MAX(Sort) amax, MIN(Sort) amin FROM A) aggA ON 1 = 1
LEFT JOIN (SELECT MAX(Sort) bmax, MIN(Sort) bmin FROM A) aggB ON 1 = 1
LEFT JOIN (SELECT MAX(Sort) cmax, MIN(Sort) cmin FROM A) aggC ON 1 = 1
ORDER BY CASE WHEN amax = amin THEN A.ID ELSE A.Sort END,
CASE WHEN bmax = bmin THEN B.ID ELSE B.Sort END,
CASE WHEN cmax = cmin THEN C.ID ELSE C.Sort END;
UPDATE2: 此尝试计算唯一的排序值和ID,并检查它们是否相同。如果它们不同,则意味着两个或多个id具有相同的排序值,因此按id排序。 也许这更接近你需要的解决方案
SELECT *
FROM A INNER JOIN B ON A.ID = B.AID
INNER JOIN C ON B.ID = C.BID
LEFT JOIN (SELECT COUNT(DISTINCT Sort) sorts, COUNT(ID) ids FROM A) aggA ON 1=1
...
ORDER BY CASE WHEN aggA.sorts <> aggA.ids THEN A.ID ELSE A.Sort END,
...
;