Sql Server - 匹配精确ID或更多

时间:2016-06-06 12:32:20

标签: sql sql-server tsql

我有一个"messages"表,其中包含以下列:"id""title"

带有列的

"categories"表:"id""title"

"messages_categories"链接表与列:"message_id""category_id"

假设我们messages的ID为

1,2,3
带有ID

categories

1,2,3

messages_categories,数据为

message: 1, category: 1

message: 2, category: 1

message: 2, category: 2

message: 3, category: 1

message: 3, category: 2

message: 3, category: 3

我想找到完全匹配或更多例如

如果我搜索类别1,我会收到消息1,2,3

如果我搜索类别1,2,我将收到消息2,3

如果我搜索类别1,2,3,我将只收到消息3

我使用了很多ID,因此每个类别的加入都可能太多。

我发现我可以在"having""sum"上使用"count"语句来查找确切的行 但这还不够好。

感谢任何帮助,Nevo。

3 个答案:

答案 0 :(得分:1)

这是relational division

1)一种解决方案是使用PIVOT:

DECLARE @filter_cat_id TABLE (cat_id INT NOT NULL PRIMARY KEY);
INSERT  @filter_cat_id VALUES (1), (2);

DECLARE @SqlStatement NVARCHAR(MAX),
    @PivotColumns NVARCHAR(MAX) = N'',
    @PivotFilters NVARCHAR(MAX) = N'';

SELECT  @PivotColumns = @PivotColumns + N', ' + QUOTENAME(f.cat_id),
        @PivotFilters = @PivotFilters + N'AND z.' + QUOTENAME(f.cat_id) + N' > 0 '
FROM    @filter_cat_id f;

SELECT  @PivotColumns = STUFF(@PivotColumns, 1, 2, N''),
        @PivotFilters = STUFF(@PivotFilters, 1, 4, N'');

--PRINT @PivotColumns
--PRINT @PivotFilters

SET @SqlStatement = N'
SELECT *
FROM (
    SELECT  x.msg_id, x.cat_id
    FROM    (VALUES 
        (1, 1),
        (2, 1),
        (2, 2),
        (3, 1),
        (3, 2),
        (3, 3)
    ) x(msg_id, cat_id)
) y
PIVOT (COUNT(y.cat_id) FOR y.cat_id IN (' + @PivotColumns + ') ) z
WHERE ' + @PivotFilters

EXEC sp_executesql @SqlStatement

例如,上面的解决方案会生成下一个[final]查询:

SELECT *
FROM (
    SELECT  x.msg_id, x.cat_id
    FROM    (VALUES 
        (1, 1),
        (2, 1),
        (2, 2),
        (3, 1),
        (3, 2),
        (3, 3)
    ) x(msg_id, cat_id)
) y
PIVOT (COUNT(y.cat_id) FOR y.cat_id IN ([1], [2]) ) z
WHERE z.[1] > 0 AND z.[2] > 0 

2)另一种解决方案使用GROUP BY和HAVING:

DECLARE @filter_cat_id TABLE (cat_id INT NOT NULL PRIMARY KEY);
INSERT  @filter_cat_id VALUES (1), (2);

SELECT  x.msg_id
FROM    (VALUES 
    (1, 1),
    (2, 1),
    (2, 2),
    (3, 1),
    (3, 2),
    (3, 3)
) x(msg_id, cat_id) -- Source table
INNER JOIN @filter_cat_id f ON x.cat_id = f.cat_id
GROUP BY x.msg_id
HAVING COUNT(x.cat_id) = (SELECT COUNT(t.cat_id) FROM @filter_cat_id t)
-- If there is not UNIQUE index/constraint on source table (msg_id + cat_id) then use COUNT(DISTINCT x.cat_id)
-- If filter_cat (cat_id) isn't unique then use COUNT(DISTINCT t.cat_id)

答案 1 :(得分:1)

如果您需要“更多”,请使用NOT EXISTS,所谓的关系师与提醒

func makeHTTPGetRequest(path: String, onCompletion: ServiceResponse) {
    let request = NSMutableURLRequest(URL: NSURL(string: path)!)
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        if let jsonData = data {
            var parseError: NSError?
            let json:JSON = JSON(data: jsonData, error: &parseError)
            onCompletion(json, parseError)
        } else {
            onCompletion(nil, error)
        }
    })
    task.resume()
}

答案 2 :(得分:0)

这可能有用:

SELECT DISTINCT x.message_id
FROM (
   **query-that-gives-the-exact-rows-but-isnt-good-enough**
) AS x