如何在 sql 中使用 parent 和 child 层次结构 select 标题?
How to select title using parent and child hierarchy in sql?
我需要搜索标题 '%p%'
。如果我检查标题,parent tile 和状态为 parent 和 child 级别。
如果搜索到的标题 parent visible 为真,则显示 child 标题。
SELECT title
FROM table1 t1
JOIN table1 t2 ON t1.title = t2.parenttitle AND t1.visible = TRUE
JOIN table1 t3 ON t3.title = t2.parenttitle AND t3.visible = TRUE
WHERE t1.title LIKE '%p%'
表 1
Title | ParentTitle|visible
P1 Home TRUE
p1.1 p1 TRUE
p1.2 p1 FALSE
p1.3 p1.2 TRUE
p1.3.1 p1.3 TRUE
p2 Home TRUE
p2.1 p2 TRUE
p2.2 p2.1 FALSE
P3 Home TRUE
p3.1 p3 TRUE
P3.1.1 p3.1 FALSE
我需要像
这样的输出
title
p1
p1.1
p2
p2.1
P3
p3.1
CREATE TABLE CTE(
Title VARCHAR(20),
ParentTitle VARCHAR(20),
visible VARCHAR(20),
)
INSERT INTO CTE
VALUES
('p1', 'Home', 'TRUE'),
('p1.1', 'p1', 'TRUE'),
('p1.2', 'p1', 'FALSE'),
('p1.3', 'p1.2', 'TRUE'),
('p1.3.1', 'p1.3', 'TRUE'),
('p2', 'Home', 'TRUE'),
('p2.1', 'p2', 'TRUE'),
('p2.2', 'p2.1', 'FALSE'),
('P3', 'Home', 'TRUE'),
('p3.1', 'p3', 'TRUE'),
('P3.1.1', 'p3.1', 'FALSE')
; WITH YTE AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RN,
DENSE_RANK() OVER(ORDER BY LEFT(A.Title, 2)) AS DR
FROM CTE A
)
, ZTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RNFalse
FROM YTE A
WHERE A.visible = 'FALSE'
)
, ATE AS
(
SELECT A.Title
FROM YTE A
INNER JOIN ZTE B ON A.DR = B.DR AND A.RN < B.RN
WHERE RNFalse = 1
) SELECT * FROM ATE
/*
Output:
p1
p1.1
p2
p2.1
P3
p3.1
*/
如果不想使用普通的table表达式,那么使用子查询
SELECT A.Title FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RN
FROM CTE A
) AS A
INNER JOIN
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RNFalse
FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RN
FROM CTE A
) A
WHERE A.visible = 'FALSE'
) AS B ON LEFT(A.Title, 2) = LEFT(B.Title, 2) AND A.RN < B.RN
WHERE B.RNFalse = 1
所以如果你想删除 ROW_NUMBER
那么你必须比较 varchar
这不好。但你没有别的办法留给我。试试这个,
SELECT A.Title FROM CTE A
INNER JOIN
(
SELECT LEFT(Title, 2) AS TitleGroup, Min(Title) AS Title
FROM CTE
WHERE visible = 'False'
GROUP BY LEFT(Title, 2)
) B ON LEFT(A.Title, 2) = B.TitleGroup
AND A.Title < B.Title --Comparing String like this is not good
我需要搜索标题 '%p%'
。如果我检查标题,parent tile 和状态为 parent 和 child 级别。
如果搜索到的标题 parent visible 为真,则显示 child 标题。
SELECT title
FROM table1 t1
JOIN table1 t2 ON t1.title = t2.parenttitle AND t1.visible = TRUE
JOIN table1 t3 ON t3.title = t2.parenttitle AND t3.visible = TRUE
WHERE t1.title LIKE '%p%'
表 1
Title | ParentTitle|visible
P1 Home TRUE
p1.1 p1 TRUE
p1.2 p1 FALSE
p1.3 p1.2 TRUE
p1.3.1 p1.3 TRUE
p2 Home TRUE
p2.1 p2 TRUE
p2.2 p2.1 FALSE
P3 Home TRUE
p3.1 p3 TRUE
P3.1.1 p3.1 FALSE
我需要像
这样的输出title
p1
p1.1
p2
p2.1
P3
p3.1
CREATE TABLE CTE(
Title VARCHAR(20),
ParentTitle VARCHAR(20),
visible VARCHAR(20),
)
INSERT INTO CTE
VALUES
('p1', 'Home', 'TRUE'),
('p1.1', 'p1', 'TRUE'),
('p1.2', 'p1', 'FALSE'),
('p1.3', 'p1.2', 'TRUE'),
('p1.3.1', 'p1.3', 'TRUE'),
('p2', 'Home', 'TRUE'),
('p2.1', 'p2', 'TRUE'),
('p2.2', 'p2.1', 'FALSE'),
('P3', 'Home', 'TRUE'),
('p3.1', 'p3', 'TRUE'),
('P3.1.1', 'p3.1', 'FALSE')
; WITH YTE AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RN,
DENSE_RANK() OVER(ORDER BY LEFT(A.Title, 2)) AS DR
FROM CTE A
)
, ZTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RNFalse
FROM YTE A
WHERE A.visible = 'FALSE'
)
, ATE AS
(
SELECT A.Title
FROM YTE A
INNER JOIN ZTE B ON A.DR = B.DR AND A.RN < B.RN
WHERE RNFalse = 1
) SELECT * FROM ATE
/*
Output:
p1
p1.1
p2
p2.1
P3
p3.1
*/
如果不想使用普通的table表达式,那么使用子查询
SELECT A.Title FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RN
FROM CTE A
) AS A
INNER JOIN
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RNFalse
FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY LEFT(A.Title, 2) ORDER BY A.Title) AS RN
FROM CTE A
) A
WHERE A.visible = 'FALSE'
) AS B ON LEFT(A.Title, 2) = LEFT(B.Title, 2) AND A.RN < B.RN
WHERE B.RNFalse = 1
所以如果你想删除 ROW_NUMBER
那么你必须比较 varchar
这不好。但你没有别的办法留给我。试试这个,
SELECT A.Title FROM CTE A
INNER JOIN
(
SELECT LEFT(Title, 2) AS TitleGroup, Min(Title) AS Title
FROM CTE
WHERE visible = 'False'
GROUP BY LEFT(Title, 2)
) B ON LEFT(A.Title, 2) = B.TitleGroup
AND A.Title < B.Title --Comparing String like this is not good