【问题标题】:Query to return the number of times a specific value occurs within a string?查询返回特定值在字符串中出现的次数?
【发布时间】:2014-01-19 00:14:35
【问题描述】:

好的,所以我有两张桌子。表 1 有一个参考编号列 (A),第二列有一个随机字符串 (B)。 Table2 只有一列,其中列出了可能在也可能不在 Table1 的字符串中的值。

dbo.Tbl_1

+--+---------------------------------------+
|A |B                                      |
+--+---------------------------------------+
|24|BLUE; KITTEN; WHITE; PINK; SLOPE; GREEN|
+--+---------------------------------------+
|51|GREEN; CLOUDY; WHITE; CHIPS            |
+--+---------------------------------------+
|78|PATRIOTS; PINK; PINK; WHITE            |
+--+---------------------------------------+
|22|WHITE; RED; TREES; AMY; GREEN          |
+--+---------------------------------------+

dbo.Tbl_2

+-----+
|C    |
+-----+
|BLUE |
+-----+
|WHITE|
+-----+
|PINK |
+-----+
|BROWN|
+-----+

什么 sql 查询将确定 Table2 中的值在 Table1 的字符串中出现的次数?基本上我想返回以下结果集:

+-----+----+
|BLUE |1   |
+-----+----+
|WHITE|4   |
+-----+----+
|PINK |3   |
+-----+----+
|BROWN|NULL|
+-----+----+

仅供参考:实际上,Table2 有大约 200 条唯一记录。表 1 有大约 160 万条具有唯一参考编号的记录。两个表都不是静态的。

【问题讨论】:

  • 在 tbl 1 col B 中是否总是只有一个颜色实例?即在 tbl 1 id 24 中,同一条记录上永远不可能有两次 BLUE
  • 与其问“我是如何做到的”,不如自己尝试一些查询,并告诉我们您尝试了什么以及哪些具体不起作用。
  • 对不起蒂姆!谢谢你告诉我!
  • @Bethany_93 你的表dbo.Tbl_1 不是正常形式。为什么?

标签: sql sql-server subquery


【解决方案1】:

我玩了一下,想出了这个SQL fiddle

相关的 SELECT 查询看起来像这样(不过需要两次表扫描,我相信它可以提高效率):

select C, sum(dbo.CountOccurancesOfString(B, C)) as number
from Tbl_1 join Tbl_2 on 1=1
group by C
order by number desc

EDIT这是我从this answer得到的函数:

CREATE FUNCTION dbo.CountOccurancesOfString
(
 @searchString nvarchar(max),
 @searchTerm nvarchar(max)
)
RETURNS INT
AS
BEGIN
 return (LEN(@searchString)-LEN(REPLACE(@searchString,@searchTerm,'')))/LEN(@searchTerm)
END

【讨论】:

  • 只有当 Tbl_2 中的所有值都是表中其他项目的子字符串时,此解决方案才有效。例如,GREEN 与 LIGHTGREEN(在这种情况下,GREEN 将被重复计算)。
  • wdosanjos - 你当然是对的。我认为 M.Ali 的拆分方法更好,因为 countoccurrences 函数必须彻底改变。
【解决方案2】:

拆分函数

CREATE FUNCTION [dbo].[udf_Split]
(
    @RowData nvarchar(2000),
    @SplitOn nvarchar(5)
)  
RETURNS @RtnValue table 
(
    Id int identity(1,1),
    Data nvarchar(100)
) 
AS  
BEGIN 
    Declare @Cnt int
    Set @Cnt = 1

    While (Charindex(@SplitOn,@RowData)>0)
    Begin
        Insert Into @RtnValue (data)
        Select 
            Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

        Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
        Set @Cnt = @Cnt + 1
    End

    Insert Into @RtnValue (data)
    Select Data = ltrim(rtrim(@RowData))

    Return
END

您的数据

DECLARE @Table_1 TABLE ([A] INT,[B] VARCHAR(1000)) 
INSERT INTO @Table_1 VALUES
(24,'BLUE; KITTEN; WHITE; PINK; SLOPE; GREEN'),
(51,'GREEN; CLOUDY; WHITE; CHIPS'), 
(78,'PATRIOTS; PINK; PINK; WHITE'), 
(22,'WHITE; RED; TREES; AMY; GREEN')

DECLARE @Table_2 TABLE (ColumnName VARCHAR(100))
INSERT INTO @Table_2 VALUES 
('BLUE'),('WHITE'),('PINK'),('BROWN')

查询

SELECT T2.ColumnName, TotalNums
 FROM 
(SELECT Data, COUNT(DATA) TotalNums 
FROM  @Table_1 t  CROSS APPLY (SELECT * FROM [dbo].[udf_Split](t.B, ';'))C
GROUP BY Data) T1
RIGHT JOIN @Table_2 T2 
ON T1.Data = T2.ColumnName

结果集

╔════════════╦═══════════╗
║ ColumnName ║ TotalNums ║
╠════════════╬═══════════╣
║ BLUE       ║ 1         ║
║ WHITE      ║ 4         ║
║ PINK       ║ 3         ║
║ BROWN      ║ NULL      ║
╚════════════╩═══════════╝

【讨论】:

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