Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.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_Linkage_Cross Join_Set Theory - Fatal编程技术网

SQL:用集合论匹配记录

SQL:用集合论匹配记录,sql,linkage,cross-join,set-theory,Sql,Linkage,Cross Join,Set Theory,我最近一直在为一个复杂的SQL查询而挣扎。 我有以下表格: [dbo].[User] ~ {ID,nickname} [dbo].[Property] ~ {ID,title} [dbo].[Property_Values] ~ [ID,propertyID,title} [dbo].[Property_Values_User_Linkage] ~ {UserID,PropertyID,valueID} 它基本上是一个由用户为每个属性选择值的项目。每个属性可以是单值或多值。例如

我最近一直在为一个复杂的SQL查询而挣扎。
我有以下表格:

[dbo].[User] ~ {ID,nickname}  
[dbo].[Property] ~ {ID,title}  
[dbo].[Property_Values] ~ [ID,propertyID,title}  
[dbo].[Property_Values_User_Linkage] ~ {UserID,PropertyID,valueID}  
它基本上是一个由用户为每个属性选择值的项目。每个属性可以是单值或多值。例如,用户可以为属性{ID=1,title=cabiods}选择多个值,但必须为属性{ID=2,title=HairColor}选择一个值

使用另一个表-[dbo]。[Search\u Property\u Values\u User\u Linkage]{UserID,PropertyID,valueID}我正在选择我想要的属性,我希望找到匹配的用户。但是,如果我没有为HairColor选择一个值(或多个值),我应该得到所有用户(因为我不想按HairColor过滤)

到目前为止,这很容易,但我似乎无法解决的问题是,前面有多个值,或者没有用户定义的值。例如,我希望所有HairColor=Brown且爱好(篮球、足球)的用户

我可以检索与其中一个术语匹配的所有用户(以及那些具有其他属性的用户,因为我没有选择对它们进行筛选),但我无法仅检索完全符合我的条件的用户

要将代码转换为文字,我们只需假设我需要所有以下用户:

  • 匹配我选择的所有属性值
  • 可能有其他属性,例如EyesColor,但由于我没有选择过滤值,因此也可能会检索它们
  • 可能根本没有设置任何属性,但由于我没有为此属性选择值,因此它们是有效的
  • 将所有选定的属性作为组进行匹配,而不仅仅是我选择的一个属性(喜欢篮球但其名称为“红色”的用户) 发色无效
我遇到了一个解决方案,其中我创建了一个虚拟表,它按位“完成”未选择的值。例如(不是实际代码):

我基本上将[Property]与[User]交叉连接
左-外-连接其他表以匹配所选内容。
我将所有用户及其匹配项设置为一个属性。这还不够好,因为我会设置棕色头发的用户、喜欢篮球/足球的用户,但不会同时设置两者(当然还有我未定义的任何其他属性)。
这很沉重,但这是我到目前为止所得到的分析问题的结果

我很感激任何帮助。我想我在10年前的数学课上错过了一些东西

编辑:db pic:

数据模型 从您的评论中,我看到您有一些其他与属性相关的表,您在问题中没有提到。我假设我们现在可以忽略这些表,只关注表示属性值,这可以通过下面的简化模型完成:

DDL SQL(MS SQL Server):

多值由用户\u属性\u值中的多行表示,这些行共享相同的属性\u名称,但每个行具有不同的属性\u值\u编号

下面的示例数据

Rob:   HairColor={brown}, Hobby={basketball,football}
Bob:   HairColor={brown}, Hobby={basketball}
Steve: Hobby={basketball,football}
…在数据库中表示为:

用户:

用户属性值:

USER_ID PROPERTY_NAME   PROPERTY_VALUE_NO   PROPERTY_VALUE
1       HairColor       1                   brown
1       Hobby           1                   basketball
1       Hobby           2                   football
2       HairColor       1                   brown
2       Hobby           1                   basketball
3       Hobby           1                   basketball
3       Hobby           2                   football
示例查询 选择具有棕色头发颜色的用户:

SELECT *
FROM [USER]
WHERE
    EXISTS (
        SELECT *
        FROM USER_PROPERTY_VALUE 
        WHERE
            USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
            AND PROPERTY_NAME = 'HairColor'
            AND PROPERTY_VALUE = 'brown'
    )
结果:

USER_ID NICKNAME
1       Rob
2       Bob
USER_ID NICKNAME
1       Rob
3       Steve
USER_ID NICKNAME
1       Rob
选择爱好包括篮球和足球的用户:

SELECT *
FROM [USER]
WHERE
    EXISTS (
        SELECT *
        FROM USER_PROPERTY_VALUE 
        WHERE
            USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
            AND PROPERTY_NAME = 'Hobby'
            AND PROPERTY_VALUE = 'basketball'
    )
    AND EXISTS (
        SELECT *
        FROM USER_PROPERTY_VALUE 
        WHERE
            USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
            AND PROPERTY_NAME = 'Hobby'
            AND PROPERTY_VALUE = 'football'
    )
结果:

USER_ID NICKNAME
1       Rob
2       Bob
USER_ID NICKNAME
1       Rob
3       Steve
USER_ID NICKNAME
1       Rob
选择头发颜色为棕色且爱好包括篮球和足球的用户

SELECT *
FROM [USER]
WHERE
    EXISTS (
        SELECT *
        FROM USER_PROPERTY_VALUE 
        WHERE
            USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
            AND PROPERTY_NAME = 'HairColor'
            AND PROPERTY_VALUE = 'brown'
    )
    AND EXISTS (
        SELECT *
        FROM USER_PROPERTY_VALUE 
        WHERE
            USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
            AND PROPERTY_NAME = 'Hobby'
            AND PROPERTY_VALUE = 'basketball'
    )
    AND EXISTS (
        SELECT *
        FROM USER_PROPERTY_VALUE 
        WHERE
            USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
            AND PROPERTY_NAME = 'Hobby'
            AND PROPERTY_VALUE = 'football'
    )
结果:

USER_ID NICKNAME
1       Rob
2       Bob
USER_ID NICKNAME
1       Rob
3       Steve
USER_ID NICKNAME
1       Rob
等等,等等

基于另一个表的内容进行查询 假设您有一个包含筛选条件的表:

CREATE TABLE PROPERTY_FILTER (
    PROPERTY_NAME nvarchar(50) NOT NULL,
    PROPERTY_VALUE nvarchar(255) NOT NULL,
    CONSTRAINT PK_PROPERTY_FILTER PRIMARY KEY (PROPERTY_NAME, PROPERTY_VALUE)
)
以下查询将仅返回满足该表中当前包含的条件的用户:

SELECT *
FROM [USER] U
WHERE
    NOT EXISTS (
        SELECT F.PROPERTY_NAME, F.PROPERTY_VALUE
        FROM PROPERTY_FILTER F
        EXCEPT
        SELECT P.PROPERTY_NAME, P.PROPERTY_VALUE
        FROM USER_PROPERTY_VALUE P
        WHERE P.USER_ID = U.USER_ID
    )
通俗地说:如果有一个筛选器属性不是用户的属性,请忽略该用户


顺便说一句,这在并发多用户环境中不起作用-您需要在PROPERTY_FILTER表中引入一个附加字段来标识“session”,或者使用(如果不需要持久性)。

是属性的数量(单个或多个值)修正?我的意思是以后是否会添加或删除属性?请告诉我单值属性是否会在任何时候变为多值属性?是否所有用户都有相同数量的属性?此外,如果没有用户,属性的存在是否有意义?我的意思是,如果没有用户输入,d记录上写着property1:value=hobby,property2:value=children等是否有意义?是的,单个值可能会被更改为多个值。所有用户都可以选择相同的属性,但可能选择只设置少数属性,而不是全部属性。是的,属性显示在用户的配置文件中,用户可以在其中设置这些属性,没有相对的相关性两者之间的连接。谢谢!!!外键是什么?具体来说,您是否使用标识外键(即您是否将父主键转换为子主键)?当然。每个存储propertyID的表实际上链接到[dbo].[Property].[ID]。每个存储valueID的表实际上链接到[dbo].[Property\U Values][ID].等等……但我不太明白这与我正在寻找的查询有什么关系(?)感谢你给出了深刻的答案!但是,对每个属性进行exists查询不允许动态查询,当然,对于大规模应用程序来说效率很低。正如我提到的,我们还有另一个表:[dbo]。[Search\u property\u Values\u User\u Linkage]这是USER_PROPERTY_VALUE的副本,但表示我要筛选的属性。我正在寻找您实现的确切想法,只是动态的(例如使用两个表之间的联接)。再次感谢,我非常感谢!@S_S请澄清“动态”是什么意思?您实际上是指带有绑定参数的查询吗(谁的SQL文本不需要更改)?或者您指的是基于另一个表的内容进行过滤(如果是,您打算如何使其在多用户环境中工作)?顺便说一句,这些子查询中的每一个都可能非常有效(如果索引构造正确)-这实际上是一个emu