【问题标题】:TSQL Finding Data in a Stuffed comma separated stringTSQL 在填充逗号分隔的字符串中查找数据
【发布时间】:2016-06-29 16:17:19
【问题描述】:

我有一个无论如何都不漂亮的查询。它非常动态,并且由于它在我的应用程序中的用例而成为这种方式。简而言之,它允许用户选择他们想在报告中看到的字段,以及定义逻辑(WHERE 子句)以及最后他们想要排序的顺序。

为了简化此操作,我创建了一个包含所有可能包含在报告中的数据的视图。这样,它只是选择用户想要的字段并查询视图。

我现在遇到了一个实例,我遇到了一些1:many 情况,而不仅仅是单个数据点。一个例子是受影响国家的列表。在我看来,它是一个逗号分隔的列表United States, United Kingdom, Etc。这些数据只是在视图创建中填充并用逗号分隔。

问题

在创建这个时,我打算只对数据使用 IN 语句。然后我意识到IN 只是一个表函数,不能用于一串数据。

有没有办法获取一个值并将其与逗号分隔的数据字符串进行比较?

我试图创建一个 SQL Fiddle,但该网站不断崩溃。

CREATE TABLE Test (country varchar(100), account INT);
INSERT INTO Test ('United States, United Kingdom', '123');
INSERT INTO Test ('United States', '123567');
INSERT INTO Test ('United States, China, Japan', '123567');

-- Trying to find all the rows where `United States` is in the country column.

我曾尝试使用LIKE %country%,但它的功能与IN 不同,因为如果该国家/地区的一部分位于另一个国家/地区名称中,我将不需要这些数据。

是否可以创建任何类型的函数来充当 IN 语句,我可以在其中针对逗号分隔的字符串测试值?

【问题讨论】:

  • 我编辑了我的答案以反映更像IN-clause 的行为。您的“爱尔兰”和“北爱尔兰”将得到正确处理...

标签: sql-server tsql stored-procedures sql-server-2012 dynamic-sql


【解决方案1】:

你可以这样做:

SELECT * FROM Test
WHERE ' ' + country + ',' LIKE '% United States,%'

这将避免返回包含另一个国家/地区名称的国家/地区。

正如@BenJaspers 所述,爱尔兰和北爱尔兰将是一个例外,因此您可以这样做:

SELECT * FROM Test
WHERE ',' + country + ',' LIKE '%, United States,%'
   OR ',' + country + ',' LIKE '%,United States,%'

【讨论】:

  • 这只是部分工作。如果我们选择爱尔兰和北爱尔兰,那么搜索爱尔兰仍然会返回两者。您必须检查字符串 LIKE 'United States,%' OR LIKE '%, United States,%' 之前是否有逗号
  • @BenJaspers 你是对的,我想不出一个例子来测试所有异常:)
【解决方案2】:

试试这样:

CREATE TABLE #Test (country varchar(100), account INT);
INSERT INTO #Test VALUES('United States, United Kingdom', '123');
INSERT INTO #Test VALUES('United States', '123567');
INSERT INTO #Test VALUES('United States, China, Japan', '123567');
INSERT INTO #Test VALUES('Ireland, United States, Japan', '123567');
INSERT INTO #Test VALUES('Northern Ireland, China, Japan', '123567');

DECLARE @SearchCountry VARCHAR(100)='Ireland';

WITH MyCTE AS
(
    SELECT account 
          ,country
          --The string will be splitted at its commas and is returned as XML in parts
          ,CAST('<x>' + REPLACE(country,', ','</x><x>') + '</x>' AS XML) AS CountrySplitted
    FROM #Test
)

SELECT * 
FROM MyCTE
--the first part of the xml is evaluated (may be with LIKE too)
WHERE CountrySplitted.exist('/x[text()=sql:variable("@SearchCountry")]')=1

DROP TABLE #Test;

【讨论】:

  • 这可能会帮助我非常接近。我如何在下一行中按值搜索而不是变量? sql:variable("@SearchCountry")
  • @SBB 只需将其替换为“您的价值”(双引号)
  • 我试过了,给了我一个关于 SQL vars 需要 @ 符号的错误。我刚刚脱下 sql:variable 并使用了 text()="My Value"
  • 上述评论现已解决。仍在尝试将您的答案纳入我的方案。 xpath 是否提供针对多个值的测试? field.exist('/data/val[text()=("var1, var2")]')=1
  • @SBB,您可以做的是field.exist('/data/val[text()="var1" or text()="var2"]')=1 XML 方法exist() 的构建目标是在第一次点击时停止。这应该是最快的解决方案(只要您将数据保存在 XML 中)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 2018-03-16
  • 1970-01-01
相关资源
最近更新 更多