Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在sql表中精确匹配标记/标签列表_Sql_Sql Server - Fatal编程技术网

在sql表中精确匹配标记/标签列表

在sql表中精确匹配标记/标签列表,sql,sql-server,Sql,Sql Server,我需要获取与标签或标记列表完全匹配的行。我有一个标签主表、带有标签FK的ContentLabels表和一个内容表 内容表: Id、名称、客户Id 标签表:Id,文本 ContentLabels表: 内容ID,LabelId 我有一个标签列表(任意数量的标签),我希望在从sql查询数据时完全匹配这些标签。我在某处尝试了以下解决方案: DECLARE @LabelTexts NVARCHAR(MAX) = 'coke,edible,chips'; DECLARE @Labels AS TABLE(

我需要获取与标签或标记列表完全匹配的行。我有一个标签主表、带有标签FK的ContentLabels表和一个内容表

内容表: Id、名称、客户Id

标签表:Id,文本

ContentLabels表: 内容ID,LabelId

我有一个标签列表(任意数量的标签),我希望在从sql查询数据时完全匹配这些标签。我在某处尝试了以下解决方案:

DECLARE @LabelTexts NVARCHAR(MAX) = 'coke,edible,chips';
DECLARE @Labels AS TABLE(
    [Text] NVARCHAR(128)
);
INSERT INTO @Labels ([Text])
SELECT [Data] FROM StrSplit(@LabelTexts, ',')

DECLARE @LabelsCount INT = (SELECT COUNT(*) FROM @Labels);

        SELECT  c.[CustomerID] ,
                c.[ContentID] AS Id ,
                c.ClusterId
         FROM ContentLabels cbl
         JOIN Labels l ON l.ClusterId = cbl.LabelClusterId
         JOIN Content c ON c.ClusterId = cbl.ContentClusterId
         GROUP BY c.[CustomerID], 
                c.[ContentID],
                c.ClusterId
        HAVING 
            COUNT(DISTINCT CASE WHEN l.[Text] IN( 'coke','chips','edible') THEN l.[Text] END)=@LabelsCount
            AND COUNT(DISTINCT CASE WHEN l.[Text] NOT IN( 'coke','chips','edible') THEN l.[Text] END) = 0;
当执行上述查询时,它工作得非常好,因为我在Having子句中的in子句中以硬形式添加了标记/标签。但当我在HAVING子句中添加以下查询时:

HAVING COUNT(DISTINCT CASE WHEN l.[Text] IN(SELECT * FROM @Labels) THEN l.[Text] END)=@LabelsCount
            AND COUNT(DISTINCT CASE WHEN l.[Text] NOT IN(SELECT * FROM @Labels) THEN l.[Text] END) = 0;
我得到以下错误:

无法对包含聚合或子查询的表达式执行聚合函数

这只是因为

从@Labels中选择*

在有从句时。花了好几个小时寻找解决方案,但没有成功。任何帮助都是值得称赞的。

请像以下那样使用操作员:

HAVING COUNT(DISTINCT CASE WHEN ',' + @LabelTexts + ',' LIKE '%,' + l.[Text] + ',%' THEN l.[Text] END) = @LabelsCount
   AND COUNT(DISTINCT CASE WHEN ',' + @LabelTexts + ',' NOT LIKE '%,' + l.[Text] + ',%' THEN l.[Text] END) = 0;

您需要左键加入所需的匹配项,然后执行条件聚合

这种类型的查询称为“无余数的关系除法”,请参见等人的相关内容

SELECT  c.[CustomerID] ,
                c.[ContentID] AS Id ,
                c.ClusterId
    FROM ContentLabels cbl
    JOIN Labels l ON l.ClusterId = cbl.LabelClusterId
    JOIN Content c ON c.ClusterId = cbl.ContentClusterId
    LEFT JOIN @labels labelMatches ON labelMatches.[Text] = l.[Text]
    GROUP BY c.[CustomerID], 
        c.[ContentID],
        c.ClusterId
    HAVING 
        COUNT(DISTINCT labelMatches.[Text] END)=@LabelsCount
        AND COUNT(CASE WHEN labelMatches.[Text] IS NULL THEN 1 END) = 0;

您可以组合使用
不退出
分组方式

SELECT 
    c.[CustomerID]
    , c.[ContentID]
    , c.ClusterId
FROM Content c
JOIN ContentLabels cl
JOIN Labels l ON l.ClusterId = cl.LabelClusterId
WHERE NOT EXISTS 
(
    -- to filter out c.ClusterId values being related to labels NOT IN the specified list
    SELECT 1
    FROM ContentLabels cl2
    JOIN Labels l2 ON l2.ClusterId = cl2.LabelClusterId
    WHERE (l2.[Text] NOT IN(SELECT * FROM @Labels)) 
            AND c.ClusterId = cl2.ContentClusterId
)
GROUP BY  
    c.[CustomerID]
    , c.[ContentID]
    , c.ClusterId
HAVING COUNT(DISTINCT l.[Text]) = @LabelsCount

上面看起来像是T-SQL,而不是MySQL,为什么在这里都加上标签?你不明白这个错误是怎么回事,因为它告诉了你问题所在。@Larnu我得到的解决方案是从MySql查询中得到的,我把它改成了t-Sql。是的,这个错误是可以理解的,但我不知道它的解决办法。我已经尝试连接标签,但没有成功。您不能将子查询放在聚合中,您需要将其放在其他位置。是的,但需要将该查询添加到何处。它正在对数据集进行计数,我尝试在该查询之前进行计数,并直接在having子句中应用,但没有效果。如果将
SELECT*FROM@Labels
替换为
SELECT[data]FROM StrSplit(@LabelTexts,,)
,会发生什么<代码>输入(选择*..无论如何都是错误的,
输入(选择[文本]…
会更符合逻辑。这不起作用,它带来了有任何标签的行。标签不完全相同。@Harry.Naeem检查这个简化的情况:代码应该可以工作。将示例数据发布到测试中。是的,它工作了,感谢解决方案就是这样。这完全按照预期工作。Giorgos Betsos answer也可以工作,但我更喜欢它这是左连接解决方案。感谢manthanks的解决方案。它正在按预期工作。