在逗号分隔列表中查找不同表

时间:2015-11-30 17:49:39

标签: sql tsql sql-server-2012

我们有一张桌子可以容纳我们的客户,他们拥有的产品以及他们订阅的城市。 cities字段是逗号分隔的数字列表。

他们想要一个存储过程,该存储过程将找到所有具有他们传入的特定城市ID的客户,但他们希望能够传递多个城市ID。

实施例 他们希望找到订阅了22和/或900的所有客户(两者都是不同的城市)。

我需要所有拥有这些城市中的一个或另一个或两个城市的客户使用逗号分隔列表。

所以我需要一种方法来搜索该列表中的第一个值,然后在列表中搜索第二个值。我正在考虑使用递归CTE,但我需要加入City表(我创建的临时表以分隔他们通过的城市ID列表)并且我不能。

当他们将city_id放入时,我将该列表分成一个表,该表具有每个城市ID,因为它在临时表中是自己的记录。帮助

请不要说停止存储以逗号分隔的列表......我无法改变我们系统功能的这一部分,这是无用的。 (我在寻找这个问题的答案时已多次见过它。)

Customer    |Product_ID     |Cities
6           | 49            |ALL
9           | 2760          |ALL                                                                                                                                                                                                                  
9           | 3618          |ALL                                                                                                                                                                                                                  
9           | 3981          |ALL                                                                                                                                                                                                                  
10          | 2760          |ALL                                                                                                                                                                                                                  
10          | 3618          |ALL                                                                                                                                                                                                                  
10          | 3981          |ALL
11          | 3981          |ALL
12          | 3981          |ALL
20          | 2894          |10,12,14,16,18,20,22,26,32,085,615,34,38,39,46,620,50,60,65,365,70,73,680,375,405,77,80,90,435,705
91          | 501           |510,515,520,521,522,523,525,526,527,530,535,540,542,545,550,553,555,560,563,565,566,567,569,570,571,572,573,574,575,20,22,576,580,581,582,585,587,590,591,593,595,598,600,610,612,614,615,617,618,619,620,621,623,625

我会搜索上面的内容,寻找20或900,这是一个非常小的样本。 ALL很简单,我知道该怎么做。在尝试查找多个城市ID时,它会搜索列表中的问题。我只是在寻找一个人的时候能够做到这一点,它做的不止一个是杀手。

我在开始时这样做:

CREATE TABLE #City 
     ( Order_ID INT
     , City_ID  VARCHAR(100)
     , FirstCitySearchText VARCHAR(100) NULL
     , LastCitySearchText VARCHAR(100)  NULL
     , OnlyCitySearchText VARCHAR(100)  NULL
       PRIMARY KEY (Order_ID, City_ID)
     )

INSERT INTO #City
SELECT i.listpos
     , i.quotedtext
     , NULL
     , NULL
     , NULL
  FROM opiscommon.dbo.SplitCommaSeparatedList(@City_IDs) i

UPDATE c
   SET c.FirstCitySearchText = '%'  + CAST(c.City_ID AS VARCHAR)+ ',%'
     , c.LastCitySearchText = '%,' + CAST(c.City_ID AS VARCHAR) + '%'
     , c.OnlyCitySearchText = '%,'  + CAST(c.City_ID AS VARCHAR) + ',%'
  FROM #City c

3 个答案:

答案 0 :(得分:4)

有时你会被别人的糟糕设计决定所困扰。您应该了解将ID存储在列表中,将数值存储为字符串以及没有声明外键关系的外键有多糟糕。

但是,当你被困住时,有方法。以下是使用EntityManager#find()的方法:

like

答案 1 :(得分:2)

这是22的逻辑。重复所有数字

where city = '22'  -- exact match
or city like '22,%' -- first item in list
or city like '%,22,%'  -- middle of list
or city like '%,22' -- last item in list

答案 2 :(得分:0)

所以我最终做的就是解决了我的问题,就像这样加入桌子:

JOIN #CityIDs c
  ON cpcpp.CUST_PROD_PARM_VAL LIKE '' + c.FirstCitySearchText + ''
  OR cpcpp.CUST_PROD_PARM_VAL LIKE '' + c.LastCitySearchText + ''
  OR cpcpp.CUST_PROD_PARM_VAL LIKE '' + c.OnlyCitySearchText + ''
  OR cpcpp.CUST_PROD_PARM_VAL LIKE '' + c.City_ID + ''
  OR cpcpp.CUST_PROD_PARM_VAL LIKE 'ALL'

这就是那些搜索文本字段:

UPDATE c
   SET c.FirstCitySearchText = CAST(c.City_ID AS VARCHAR(100))+ ',%'
     , c.LastCitySearchText = '%,' + CAST(c.City_ID AS VARCHAR(100))
     , c.OnlyCitySearchText = '%,'  + CAST(c.City_ID AS VARCHAR(100)) + ',%'
  FROM #CityIDs c

我无法使用发布的where子句,因为我不确定如何加入表来获取城市ID,所以我使用where子句作为连接加入了它们。

这不是一个好的解决方案,但它是目前唯一有效的解决方案。我收回了我期望的结果,存储过程只需要大约20秒就可以运行,这被认为是胜利。