有问题的地方
形式提供了几个表
我已经以MainRecord
Record ID Details Textual Information
1 AAAAAAA ... some text referring to Oxford St Giles...
2 BBBBBBB ... some text referring Oxford....
3 CCCCCCC ... some text referring to Oxford St Aldate...
,并支持表
PlaceNames
Record ID PlaceName
1 Oxford
1 St
1 Giles
2 Oxford
3 Oxford
3 St
3 Aldate
我希望能够构建一个搜索词,以便我可以输入全部或部分词关于地名。例如,如果我输入“Oxford”,我会得到所有 3 条记录,如果我输入“Oxford”和“Giles”,我只会得到记录 1 - 几乎就像使用 WHERE IN ('Oxford','Giles'),但这些术语是 AND 组合被ORed?
不知道我能不能实现这个目标?我尝试了各种子查询但没有成功
我正在使用 SQL Server 2008
我想避免创建全文搜索字段
任何清除迷雾的指针都会非常有帮助。
* 更新主要记录详细信息以避免混淆 *
两个表之间的唯一链接是记录 ID
** 更新 ** 11 月 3 日包含示例表
CREATE TABLE MAIN_RECORD (RecordID int,DocumentRef varchar(100));
INSERT INTO MAIN_RECORD VALUES (86, 'Doc Referring to William Samuel ADAMS');
INSERT INTO MAIN_RECORD VALUES (87, 'Doc Referring to William JONES');
INSERT INTO MAIN_RECORD VALUES (88, 'Doc Referring to Samuel SMITH');
CREATE TABLE FORENAMES (RecordID int,Forename varchar(25));
INSERT INTO FORENAMES VALUES (86, 'William');
INSERT INTO FORENAMES VALUES (86, 'Samuel');
INSERT INTO FORENAMES VALUES (87, 'William');
INSERT INTO FORENAMES VALUES (88, 'Samuel');
我的初始查询是
SELECT main.[RecordID],main.documentRef
FROM [MAIN_RECORD] main
INNER JOIN [FORENAMES] fn
ON main.RecordID = fn.RecordID
WHERE fn.ForeName IN ('William')
This is Fine and returns
RecordID documentRef
86 Doc Referring to William Samuel ADAMS
87 Doc Referring to William JONES
ditto with Samuel, etc
我的问题是当我在名字搜索字段中有超过 1 个条目时即
SELECT main.[RecordID],main.documentRef
FROM [MAIN_RECORD] main
INNER JOIN [FORENAMES] fn
ON main.RecordID = fn.RecordID
WHERE fn.ForeName IN ('William,Samuel')
这不会返回任何内容。
我需要这个只返回包含塞缪尔和威廉的主记录,即。当搜索词包含多个名称时。
它还需要找到威廉·塞缪尔以及塞缪尔·威廉。
从其他人的帖子中,我沿着 DIVISION 的路线走了下去,并提出了以下内容(在主 SELECT 之前放置一些字符串操作):
DECLARE @Forename nvarchar(max)
DECLARE @SQLCommand nvarchar(max)
DECLARE @Number_of_Terms int
SET @Forename = 'William,Samuel'
--SET @Forename = 'Samuel,William'
--SET @Forename = 'William'
--SET @Forename = 'Samuel'
SET @Number_of_Terms = LEN(@Forename) - LEN(REPLACE(@Forename,',',''))+1
SET @Forename = REPLACE(@Forename,',',''',''')
SET @SQLCommand = 'SELECT fr.RecordID FROM dbo.BRS109_FullRecord fr '+
'INNER JOIN dbo.BRS109_Forenames fn '+
'ON fr.RecordID = fn.RecordID '+
'WHERE fr.RecordID = fn.RecordID '+
'AND fn.forename IN ('''+@Forename +''') ' +
' GROUP BY fr.RecordID ' +
' HAVING COUNT(fr.RecordId) = ' + CAST(@Number_of_Terms AS varchar(2)) +
' ORDER BY fr.RecordId'
EXECUTE sp_executesql @SQLCommand
这似乎给了我我正在寻找的东西。
非常感谢大家的贡献,特别是“Quassnoi”和“onedaywhen”——非常有帮助
I have a couple of Tables already supplied in the form
MainRecord
Record ID Details Textual Information
1 AAAAAAA ... some text referring to Oxford St Giles...
2 BBBBBBB ... some text referring Oxford....
3 CCCCCCC ... some text referring to Oxford St Aldate...
and supporting table
PlaceNames
Record ID PlaceName
1 Oxford
1 St
1 Giles
2 Oxford
3 Oxford
3 St
3 Aldate
I want to be able to build a search term so that if I can enter all or partial terms on place names. E.g. if I enter 'Oxford' I get all 3 records, if I enter 'Oxford' and 'Giles' I only get record 1 - almost like using a WHERE IN ('Oxford','Giles') but the terms are ANDed instead of being ORed?
I don't know if I can achieve this? I have tried various sub-queries without success
I am using SQL Server 2008
I wanted to avoid making a fulltext search field
Any pointers to clear the mist would be very helpful.
* Main Record detail updated to avoid confusion *
The only link between the 2 tables is the record ID
** Updated ** Nov 03 with sample tables
CREATE TABLE MAIN_RECORD (RecordID int,DocumentRef varchar(100));
INSERT INTO MAIN_RECORD VALUES (86, 'Doc Referring to William Samuel ADAMS');
INSERT INTO MAIN_RECORD VALUES (87, 'Doc Referring to William JONES');
INSERT INTO MAIN_RECORD VALUES (88, 'Doc Referring to Samuel SMITH');
CREATE TABLE FORENAMES (RecordID int,Forename varchar(25));
INSERT INTO FORENAMES VALUES (86, 'William');
INSERT INTO FORENAMES VALUES (86, 'Samuel');
INSERT INTO FORENAMES VALUES (87, 'William');
INSERT INTO FORENAMES VALUES (88, 'Samuel');
My intial query is
SELECT main.[RecordID],main.documentRef
FROM [MAIN_RECORD] main
INNER JOIN [FORENAMES] fn
ON main.RecordID = fn.RecordID
WHERE fn.ForeName IN ('William')
This is fine and returns
RecordID documentRef
86 Doc Referring to William Samuel ADAMS
87 Doc Referring to William JONES
ditto with Samuel, etc
my problem is when I have more than 1 entry in the forename Search field i.e.
SELECT main.[RecordID],main.documentRef
FROM [MAIN_RECORD] main
INNER JOIN [FORENAMES] fn
ON main.RecordID = fn.RecordID
WHERE fn.ForeName IN ('William,Samuel')
This returns nothing.
I need this to ONLY return the MAIN record that has BOTH Samuel AND William in it, ie. when the search term has more than one name in it.
It also need to find William Samuel as well as Samuel William.
From posts by others, I have gone down the route of DIVISION and come up with the following (putting some string manipulation before main SELECT ):
DECLARE @Forename nvarchar(max)
DECLARE @SQLCommand nvarchar(max)
DECLARE @Number_of_Terms int
SET @Forename = 'William,Samuel'
--SET @Forename = 'Samuel,William'
--SET @Forename = 'William'
--SET @Forename = 'Samuel'
SET @Number_of_Terms = LEN(@Forename) - LEN(REPLACE(@Forename,',',''))+1
SET @Forename = REPLACE(@Forename,',',''',''')
SET @SQLCommand = 'SELECT fr.RecordID FROM dbo.BRS109_FullRecord fr '+
'INNER JOIN dbo.BRS109_Forenames fn '+
'ON fr.RecordID = fn.RecordID '+
'WHERE fr.RecordID = fn.RecordID '+
'AND fn.forename IN ('''+@Forename +''') ' +
' GROUP BY fr.RecordID ' +
' HAVING COUNT(fr.RecordId) = ' + CAST(@Number_of_Terms AS varchar(2)) +
' ORDER BY fr.RecordId'
EXECUTE sp_executesql @SQLCommand
This seems to give me what I am looking for.
Many thanks to all for contributing especially 'Quassnoi' and 'onedaywhen' - very helpful
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您是在暗示关系划分吗?例如提供所有产品的供应商、可以驾驶机库中所有飞机的飞行员等?
如果是这样,本文有许多 SQL 实现示例。
这是使用您的数据的一个:
更新:
我更喜欢您的原始数据;)无论如何,我建议的方法是相同的,即关系划分(这次有更好的连接):
Are you alluding to relational division? e.g. the supplier who supplies all products, the pilot that can fly all the planes in the hanger, etc?
If so, this article has many example implementations in SQL.
Here's one using your data:
UPDATE:
I preferred your original data ;) No matter, my suggested approach is the same i.e. relational division (this time with better joins):
不太确定在您的环境中,但在 Oracle 中,这个应该可以工作。
not exactly sure in your environment, but in Oracle, this one should work.
使用 LIKE 语句
像这样:
使用这个查询你不需要第二个表,
一切都会通过第一个完成
Use LIKE statement
like so:
Using this query you won't need the second table,
everything will be done through the first one
如果这就是您所需要的,您可以使用 LIKE
如果您需要更多的灵活性(例如限制匹配整个单词),您可以 轻松将正则表达式搜索添加到 SQL Server
If that's all you need, you can use LIKE
If you need a bit more flexibility (e.g. limiting matching to whole words), you can add Regex search to SQL Server easily