【问题标题】:SQL: select unique substrings from the table by maskSQL:通过掩码从表中选择唯一的子字符串
【发布时间】:2015-02-14 13:58:02
【问题描述】:

有一个 SQL 表 mytable 有一个列 mycolumn。 该列在每个单元格内都有文本。每个单元格都可能包含“this.text/31/”或“this.text/72/”子字符串(子字符串中的数字可以是任何数字)作为字符串的一部分。

应该执行什么 SQL 查询来显示唯一的此类子字符串的列表?

附:当然,某些单元格可能包含几个这样的子字符串。

以下是 cmets 问题的答案: 该查询应该在 SQL Server 上运行。 首选输出应包含整个子字符串,而不仅仅是数字部分。它实际上可能不仅仅是第一个“/”和第二个“/”之间的数字。

而且是varchar类型(可能)

示例: mycolumn 包含这样的值:

abcd/eftthis.text/31/sadflh adslkjh
abcd/eftthis.text/44/khjgb ljgnkhj this.text/447/lhkjgnkjh
ljgkhjgadsvlkgnl
uygouyg/this.text/31/luinluinlugnthis.text/31/ouygnouyg
khjgbkjyghbk

查询应该显示:

this.text/31/
this.text/44/
this.text/447/

【问题讨论】:

  • 所以你只想要数字部分?您能否根据示例数据集阐明所需的输出?
  • 所以这个单元格是varchar 类型?
  • 您的查询是否应该同时在 MySQL 和 SQL Server 上运行?
  • 为什么SELECT DISTINCT mycolumn FROM mytable 不起作用?
  • 我在上面的描述中回答了你的问题。谢谢。

标签: mysql sql sql-server select


【解决方案1】:

如何使用递归 CTE:

CREATE TABLE #myTable
(
myColumn VARCHAR(100)
)

INSERT INTO #myTable
VALUES
    ('abcd/eftthis.text/31/sadflh adslkjh'),
    ('abcd/eftthis.text/44/khjgb ljgnkhj this.text/447/lhkjgnkjh'),
    ('ljgkhjgadsvlkgnl'),
    ('uygouyg/this.text/31/luinluinlugnthis.text/31/ouygnouyg'),
    ('khjgbkjyghbk')


;WITH CTE
AS
(
    SELECT MyColumn, 
    CHARINDEX('this.text/', myColumn, 0)  AS startPos,
    CHARINDEX('/', myColumn, CHARINDEX('this.text/', myColumn, 1) + 10) AS endPos
    FROM #myTable
    WHERE myColumn LIKE '%this.text/%'
    UNION ALL
    SELECT T1.MyColumn, 
    CHARINDEX('this.text/', T1.myColumn, C.endPos) AS startPos,
    CHARINDEX('/', T1.myColumn, CHARINDEX('this.text/', T1.myColumn, c.endPos) + 10) AS endPos
    FROM #myTable T1
    INNER JOIN CTE C
        ON C.myColumn = T1.myColumn
    WHERE SUBSTRING(T1.MyColumn, C.EndPos, 100) LIKE '%this.text/%'

)
SELECT DISTINCT SUBSTRING(myColumn, startPos, EndPos - startPos)
FROM CTE

【讨论】:

    【解决方案2】:

    有一个名为 test 的表,其中包含以下数据:

    COLUMN1
    aathis.text/31/
    this.text/1/
    bbbthis.text/72/sksk
    

    这就是你要找的吗?

    select SUBSTR(COLUMN1,INSTR(COLUMN1,'this.text', 1 ),INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 )+10) - INSTR(COLUMN1,'this.text', 1 )+1) from test;
    

    结果:

    this.text/31/
    this.text/1/
    this.text/72/
    

    我看到了你的问题:

    假设与上面相同的表,但现在包含以下数据:

    this.text/77/
    xxthis.text/33/xx
    xthis.text/11/xxthis.text/22/x
    xthis.text/1/x
    

    以下内容可能会对您有所帮助:

    SELECT SUBSTR(COLUMN1, INSTR(COLUMN1,'this.text', 1 ,1), INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 ,1)+10) - INSTR(COLUMN1,'this.text', 1 ,1)+1) FROM TEST
    UNION
    SELECT CASE WHEN (INSTR(COLUMN1,'this.text', 1,2 ) >0) THEN 
           SUBSTR(COLUMN1, INSTR(COLUMN1,'this.text', 1,2 ), INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 ,2),2) - INSTR(COLUMN1,'this.text', 1,2 )+1) end FROM TEST;
    

    它将产生以下结果:

    this.text/1/
    this.text/11/
    this.text/22/
    this.text/33/
    this.text/77/
    

    缺点是您需要为每次出现的“this.text”添加一个选择语句。如果您在同一个单元格中可能有 100 个“this.text”,那可能是个问题。

    【讨论】:

      【解决方案3】:

      SQL> select SUBSTR(column_name,1,9) from tablename;

      列名


      this.text

      【讨论】:

        【解决方案4】:
        SELECT REGEXP_SUBSTR(column_name,'this.text/[[:digit:]]+/') 
        FROM table_name
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-08
          • 2016-07-03
          • 1970-01-01
          • 2011-08-11
          相关资源
          最近更新 更多