【问题标题】:sql query with substring charindex带有子字符串charindex的sql查询
【发布时间】:2017-06-14 15:42:36
【问题描述】:
table1
::::::::::::::::::::::::::::::::::
id | id_data | id_t | value 
1  | 43      | 1    | 
2  | 46      | 1    | 111,112,113
3  | 43      | 2    | 
4  | 46      | 2    | 90,5

table2
:::::::::::::::::::::::::::::::::::
id_value | cat
112      | cat1
5        | cat2

您好,如果可能的话,我需要一些帮助。

我需要用 table2.cat 更新 table1.value,其中 id_data 为 43,其中 id_value = value ',' '直到下一个 ',' 之后的数字,如果 'id_t' 中的每个组都有的话

我尝试了一个简单的查询,但它返回一些 null 但“值”不能为 null

update table1 
set value = (select cat from table2 
            where convert(nvarchar,id_value) = substring(value,5,3))
where id_data='43'

我一直在尝试合并 CHARINDEX 以从“,”中获取,但我只是无法弄清楚它是如何工作的。

理想情况下应该是这样的:

::::::::::::::::::::::::::::::::::
id | id_data | id_t | value 
1  | 43      | 1    | cat1
2  | 46      | 1    | 111,112,113
3  | 43      | 2    | cat2
4  | 46      | 2    | 90,5

谁能指出我正确的方向,好吗?

我想这很简单......但我还在学习......

提前致谢。

:::::::::::::::::

更新1

WITH UpdateableCTE AS
(
    SELECT t1.id
          ,t1.id_data
          ,t1.id_t
          ,SecondNr
          ,(
            SELECT t2.cat
            FROM @table2 AS t2 WHERE t2.id_value=SecondNr
           ) AS NewCat
           ,t1.value
    FROM @table1 AS t1
    OUTER APPLY(SELECT CAST('<x>' + REPLACE(x.value,',','</x><x>') + '</x>' AS XML).value('/x[2]','int')
                FROM @table1 AS x 
                WHERE x.id_t=t1.id_t AND x.value IS NOT NULL AND id_data='46') AS ID(SecondNr)
    WHERE t1.value IS NULL
)
UPDATE UpdateableCTE SET value=NewCat;
--somehow where id_data='43'

我将在这里留下一张看起来更像真实的表格,其中包含所有 id_data 和字段:

17974492    1   999251  somevalue
17974493    2   999251  somevalue
17974494    3   999251  somevalue
17974495    4   999251  somevalue
17974496    5   999251  somevalue
17974497    43  999251  (thishsouldbeupdated)
17974498    6   999251  somevalue
17974499    7   999251  somevalue
17974500    46  999251  111,311
17974501    8   999251  somevalue
17974502    9   999251  somevalue
17974503    10  999251  somevalue
17974504    11  999251  somevalue
17974505    12  999251  somevalue
17974506    13  999251  somevalue
17974507    1   999252  somevalue
17974508    2   999252  somevalue
17974509    3   999252  somevalue
17974510    4   999252  somevalue
17974511    5   999252  somevalue
17974512    43  999252  (thisshouldbeupdated)
17974513    6   999252  somevalue
17974514    7   999252  somevalue
17974515    46  999252  98,98
17974516    8   999252  somevalue
17974517    9   999252  somevalue
17974518    10  999252  somevalue
17974519    11  999252  somevalue
17974520    12  999252  somevalue
17974521    13  999252  somevalue

【问题讨论】:

  • 一般建议:不要将 CSV 数据存储在数据库表中。这意味着您的数据未标准化,通常难以处理。
  • 对不起,我不明白你的逻辑... 有cat1,因为下面带有id_data=46 的行在逗号之间有112,而你设置了cat2,因为以下行有5?这很奇怪,闻起来很臭......
  • id_t "groups" 他们在第一张桌子上,每个'group'都有一个id_data 46记录,每个id_t应该加入的一个ID是(第二条记录,在',')。我需要为每个 id_t 更新 id_data 43
  • @Shnugo 再次阅读您的评论,我想我现在明白您的意思了,抱歉。实际上,table1 和 table2 通过 table1 上逗号之间的第二条记录连接。我知道这有点奇怪,但我正在处理一个已经定义的表,现在无法更改。
  • @vvic,这很糟糕......如果你的第一个表有111,112,5,113,会发生什么?你会接受catcat2 还是两者兼而有之?每个id_t 总是正好有两行吗? id_data 的目的是什么? id 列的顺序是否严格(CSV 编号的行的 id 是否总是 id+1)?

标签: sql sql-server substring charindex


【解决方案1】:

这不干净,也不是我推荐的,但你可能会找到一些帮助:

DECLARE @table1 TABLE(id INT,id_data INT,id_t INT,value VARCHAR(100));
INSERT INTO @table1 VALUES 
 (1,43,1,NULL)
,(2,46,1,'111,112,113')
,(3,43,2,NULL)
,(4,46,2,'90,5')

DECLARE @table2 TABLE(id_value INT,cat VARCHAR(100));
INSERT INTO @table2 VALUES
 (112,'cat1')
,(5,'cat2');

SELECT t1.id
      ,t1.id_data
      ,t1.id_t
      ,ID.List
      ,(
        SELECT t2.cat
        FROM @table2 AS t2 WHERE CHARINDEX(',' + CAST(t2.id_value AS VARCHAR(100)) + ',',',' + ID.List + ',')>0
       )
FROM @table1 AS t1
OUTER APPLY(SELECT x.value FROM @table1 AS x WHERE x.id_t=t1.id_t AND x.value IS NOT NULL) AS ID(List)
WHERE t1.value IS NULL

更新:您对使用第二个数字作为更新的解释

试试这个

DECLARE @table1 TABLE(id INT,id_data INT,id_t INT,value VARCHAR(100));
INSERT INTO @table1 VALUES 
 (1,43,1,NULL)
,(2,46,1,'111,112,113')
,(3,43,2,NULL)
,(4,46,2,'90,5')

DECLARE @table2 TABLE(id_value INT,cat VARCHAR(100));
INSERT INTO @table2 VALUES
 (112,'cat1')
,(5,'cat2');

WITH UpdateableCTE AS
(
    SELECT t1.id
          ,t1.id_data
          ,t1.id_t
          ,SecondNr
          ,(
            SELECT t2.cat
            FROM @table2 AS t2 WHERE t2.id_value=SecondNr
           ) AS NewCat
           ,t1.value
    FROM @table1 AS t1
    OUTER APPLY(SELECT CAST('<x>' + REPLACE(x.value,',','</x><x>') + '</x>' AS XML).value('/x[2]','int')
                FROM @table1 AS x 
                WHERE x.id_t=t1.id_t AND x.value IS NOT NULL) AS ID(SecondNr)
    WHERE t1.value IS NULL
)
UPDATE UpdateableCTE SET value=NewCat;

SELECT * FROM @table1

概念是可更新的 CTE,您可以在其中使用普通的SELECT 来获取您需要的值。然后,您可以直接更新派生表(只要只有一个表的列受到影响)。

OUTER APPLY 使用 XML 的技巧来拆分 CSV 列表以读取第二个数字。

更新 2:使用新的示例数据

以下将使用新的示例数据并使用 ID:

DECLARE @table1 TABLE(id INT,id_data INT,id_t INT,value VARCHAR(100));
INSERT INTO @table1 VALUES 
 (17974492,1,999251,'somevalue')
,(17974493,2,999251,'somevalue')
,(17974494,3,999251,'somevalue')
,(17974495,4,999251,'somevalue')
,(17974496,5,999251,'somevalue')
,(17974497,43,999251,'(thishsouldbeupdated)')
,(17974498,6,999251,'somevalue')
,(17974499,7,999251,'somevalue')
,(17974500,46,999251,'111,311')
,(17974501,8,999251,'somevalue')
,(17974502,9,999251,'somevalue')
,(17974503,10,999251,'somevalue')
,(17974504,11,999251,'somevalue')
,(17974505,12,999251,'somevalue')
,(17974506,13,999251,'somevalue')
,(17974507,1,999252,'somevalue')
,(17974508,2,999252,'somevalue')
,(17974509,3,999252,'somevalue')
,(17974510,4,999252,'somevalue')
,(17974511,5,999252,'somevalue')
,(17974512,43,999252,'(thisshouldbeupdated)')
,(17974513,6,999252,'somevalue')
,(17974514,7,999252,'somevalue')
,(17974515,46,999252,'98,98')
,(17974516,8,999252,'somevalue')
,(17974517,9,999252,'somevalue')
,(17974518,10,999252,'somevalue')
,(17974519,11,999252,'somevalue')
,(17974520,12,999252,'somevalue')
,(17974521,13,999252,'somevalue');

DECLARE @table2 TABLE(id_value INT,cat VARCHAR(100));
INSERT INTO @table2 VALUES
 (311,'cat1')
,(98,'cat2');

WITH UpdateableCTE AS
(
    SELECT t1.id
          ,t1.id_data
          ,t1.id_t
          ,SecondNr
          ,(
            SELECT t2.cat
            FROM @table2 AS t2 WHERE t2.id_value=SecondNr
           ) AS NewCat
           ,t1.value
    FROM @table1 AS t1
    OUTER APPLY(SELECT CAST('<x>' + REPLACE(x.value,',','</x><x>') + '</x>' AS XML).value('/x[2]','int')
                FROM @table1 AS x 
                WHERE x.id_t=t1.id_t AND x.id_data=46) AS ID(SecondNr)
    WHERE t1.id_data=43
)
UPDATE UpdateableCTE SET value=NewCat;

SELECT * FROM @table1;

【讨论】:

  • 我想你把我弄丢了……对不起。那么,更新查询会是这样的吗? update table1 set value = ( SELECT cat FROM table2 WHERE CHARINDEX(',' + CAST(id_value AS VARCHAR(100)) + ',',',' + ID.List + ',')&gt;0 ) from table1 OUTER APPLY(SELECT x.value FROM table1 AS x WHERE x.Id_t=t1.Id_t AND x.value IS NOT NULL) AS ID(List) where Id_data='43'
  • 我正在测试它,它几乎就在那里,XML 技巧工作得很好。但是,如果我按照您的示例执行,它将获得 0 行来更新。如果我删除 WHERE t1.value IS NULL 它会更新每一行。那么如果我只想更新id_data='43' 怎么办?另外,我怎么能只在id_data='46' 上检查','而不是它不为空的地方?(除了可以包含数据的43 和46 之外,还有更多的id_data)。我将用我尝试过的内容更新原始问题。非常感谢您的帮助。
  • 我已经尝试过了,但由于一些奇怪的空值而出现错误,它现在已修复并且可以正常工作。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多