我有这张桌子树:
ID Name ParentID
-------------------
1 A NULL
2 A B 1
3 A B C 2
我想修剪名称列中的父前缀(在上面的示例中' A'在第二行中' A-B'在第三行中),父母可能为简单起见,我只是在我的例子中写了一个字母。
Update
Tree
Set
Name = REPLACE(Name,
(Select Name
Where ParetnID=@ParentID), '')
Where ParentId IS NOT NULL
我不确定如何获得@ParentID
答案 0 :(得分:1)
尝试使用LAG函数,它可以访问当前行之前的行。
.card-img-overlay {
position: absolute;
top: 0px;
right: 0px;
bottom: 0;
left: 150px;
padding: 1.25rem;
}
结果
DECLARE @ttable TABLE
(
id SMALLINT ,
name VARCHAR(10) ,
parentid SMALLINT
)
INSERT INTO @ttable
VALUES ( 1, 'A', NULL ),
( 2, 'A B', 1 ),
( 3, 'A B C', 2 )
--
;
WITH CTE
AS ( SELECT Id ,
name ,
RTRIM(LTRIM(REPLACE(name, LAG(name, 1, 0) OVER ( ORDER BY id ), ''))) rr ,
parentid
FROM @ttable
)
UPDATE CTE
SET name = rr
SELECT * FROM @ttable
答案 1 :(得分:0)
示例数据
Declare @t TABLE (ID INT , Name VARCHAR(100), ParentID INT)
INSERT INTO @t VALUES
(1 ,'A' ,NULL),
(2 ,'A B' ,1 ),
(3 ,'A B C' ,2 )
<强>查询强>
SELECT *
FROM @t t
CROSS APPLY
(
SELECT Replace(
RTRIM(LTRIM(Split.a.value('.', 'VARCHAR(100)')))
,'|' , '&') NameElement
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 NodeLevel
FROM
(
SELECT Cast ('<X>'
+ Replace(Replace(t.Name, ' ', '</X><X>'), '&' , '|')
+ '</X>' AS XML) AS Data
) AS t CROSS APPLY Data.nodes ('/X') AS Split(a)
) c(NameElement, NodeLevel)
WHERE t.ParentID = c.NodeLevel
结果集
+----+-------+----------+-------------+-----------+
| ID | Name | ParentID | NameElement | NodeLevel |
+----+-------+----------+-------------+-----------+
| 2 | A B | 1 | B | 1 |
| 3 | A B C | 2 | C | 2 |
+----+-------+----------+-------------+-----------+
SQL Server 2016及更高版本
在SQL Server 2016中,STRING_SPLIT()函数使这变得更加简单。在SQL Server 2016及更高版本中,您的查询将如下所示:
SELECT *
FROM @t t
CROSS APPLY (SELECT value
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 NodeLevel
FROM string_split(t.name , ' ')
) c(NameElement, NodeLevel)
WHERE t.ParentID = c.NodeLevel
现在您可以将此select转换为更新语句。
答案 2 :(得分:0)
从父参考更新NAME(又名父母姓名)。由于没有解释NAME字段,因此OP令人困惑。
update t
set name = (select top 1 name from tree m where t.parentid = m.id)
from tree t
答案 3 :(得分:0)
尝试以下方法:
Update Tree
Set Name = REPLACE(Name,B.Name, '')
FROM Tree A
INNER JOIN Tree B
ON A.ParentID = B.ID
Where ParentId IS NOT NULL
答案 4 :(得分:0)
可以通过这种方式简单地选择值:
select substring(cv,CHARINDEX(pv,cv)+LEN(pv),LEN(cv))
from (select ct.name cv,pt.name pv from tree ct,tree pt where pt.id=ct.parentid) r
这里是你的树表。 r是通过与自身连接的子查询。 c的前缀为child,p为parent。 必须工作
答案 5 :(得分:0)
由于您是SQL2016,因此可以使用其中的一些功能来简化这一过程。如果更改IIF()
,这应该可以返回SQL2012或SQL2008。
MS SQL Server 2017架构设置:
CREATE TABLE t ( ID int, Name varchar(10), ParentID int ) ;
INSERT INTO t
VALUES
(1,'A1',NULL)
, (2,'A1 B2',1)
, (3,'A1 B2 C3',2)
, (4,'D1',NULL)
, (5,'D1 E2',4)
, (6,'D1 E2 F3',5)
;
查询:
SELECT s1.Name
, REVERSE( IIF( s1.delim-1<0 , s1.revStr, LEFT(s1.revStr,(s1.delim-1)) ) ) AS finalStr
FROM (
SELECT Name
, REVERSE(t.Name) as revStr
, CHARINDEX(' ',REVERSE( t.Name )) as delim
FROM t
) s1
<强> Results 强>:
| Name | finalStr |
|----------|----------|
| A1 | A1 |
| A1 B2 | B2 |
| A1 B2 C3 | C3 |
| D1 | D1 |
| D1 E2 | E2 |
| D1 E2 F3 | F3 |
我做了什么:
1)FROM (...) s1
&gt;&gt;我使用子查询来防止必须计算反向字符串和分隔符的位置。
1a)如果分隔符发生变化,只需更改CHARINDEX(' ',.....)
。
2)由于我有反向字符串,我计算分隔符的位置并用LEFT(s1.revStr,(s1.delim-1))
提取该字符串。
3)由于字符串中只有一个元素(父行),我IIF()
以查看我的分隔符是否超出范围。
4)由于我已经提取了反向字符串的第一项,我现在必须将该字符串反转以恢复为原始值。