Sql 在定义存在的地方合并

Sql 在定义存在的地方合并,sql,tsql,Sql,Tsql,我这里有三张桌子属性映射,组定义,以及组映射 ATTRIBUTE\u MAP包含CUST\u ID和相关的ATTRIBUTE\u ID GROUP\u定义定义一个组。其列为组ID,属性1,值1,属性2,值2,属性3,值3组由1到3个带值的属性组成。例如,属性可以是“State”,其值为“newyork”。对于“Owns Car”等布尔值,值也可以为null GROUP\u MAP只需将CUST\u ID映射到GROUP\u ID 现在,我正在尝试编写一个脚本,查看属性映射,查看客户是否属于组定义

我这里有三张桌子<代码>属性映射,
组定义
,以及
组映射

ATTRIBUTE\u MAP
包含
CUST\u ID
和相关的
ATTRIBUTE\u ID

GROUP\u定义
定义一个组。其列为
组ID
属性1
值1
属性2
值2
属性3
值3
组由1到3个带值的属性组成。例如,属性可以是“State”,其值为“newyork”。对于“Owns Car”等布尔值,值也可以为null

GROUP\u MAP
只需将
CUST\u ID
映射到
GROUP\u ID

现在,我正在尝试编写一个脚本,查看
属性映射
,查看客户是否属于
组定义
中定义的组之一。如果他(客户)这样做,则使用
CUST\u ID
GROUP\u ID
GROUP\u MAP
中插入/更新一行。我遇到问题的部分是匹配属性值

以下是我到目前为止的情况:

merge GROUP_MAP gm using 
( select am.CUST_ID
        ,am.ATTRIBUTE_ID
        ,am.START_DATE
        ,gd.GROUP_ID
        ,gd.ATTRIBUTE_1
        ,gd.VALUE_1
        ,gd.ATTRIBUTE_2
        ,gd.VALUE_2
        ,gd.ATTRIBUTE_3
        ,gd.VALUE_3
from ATTRIBUTE_MAP am, GROUP_DEFINITIONS gd ) src
on gm.GROUP_ID=src.GROUP_ID 
    AND gm.CUST_ID=src.CUST_ID

when not matched then -- create association in GROUP_MAP
insert (CUST_ID, GROUP_ID, FROM_DATE)
values (src.CUST_ID, src.GROUP_ID, src.START_DATE);
我的做法正确吗?我想我需要改进合并中的嵌套select语句,以加入
属性映射和
对等组定义,然后从那里开始。如有任何帮助/建议,将不胜感激

以下是一个供参考的示例:

属性映射

+---------+--------------+------------+
|客户ID |属性ID |值|
+---------+--------------+------------+
|50 | 1 |“纽约”|
+---------+--------------+------------+
| 50      | 2            |            |
+---------+--------------+------------+

组定义

+----------+-------------+------------+-------------+---------+-------------+---------+
|组ID |属性|值|值| 1 |属性|值|值|值| 3|
+----------+-------------+------------+-------------+---------+-------------+---------+
|10 | 1 |纽约| 2 | ||
+----------+-------------+------------+-------------+---------+-------------+---------+
| 20       | 2           |            |             |         |             |         |
+----------+-------------+------------+-------------+---------+-------------+---------+

因此脚本应该生成(在
组映射中
):

+---------+----------+--------+
|客户ID |集团ID |日期|
+---------+----------+--------+
|50 | 10 |*日期*|
+---------+----------+--------+
|50 | 20 |*日期*|

+---------+----------+--------+

我可以完全关闭,但看起来您的内部选择应该是这样的。如果我理解您试图执行的操作,这将返回一个唯一的CUST_ID、GROUP_ID、START_DATE列表,其中所有客户属性与所有组属性匹配。只是写得这么快,所以可能会有一些错误,但它可能会让你走上正确的方向

with gd as (
  SELECT GROUP_ID, ATTRIBUTE_1 as ATTRIBUTE_ID, VALUE_1 as VALUE from GROUP_DEFINITIONS 
  UNION
  SELECT GROUP_ID, ATTRIBUTE_2, VALUE_2 from GROUP_DEFINITIONS 
  UNION
  SELECT GROUP_ID, ATTRIBUTE_3, VALUE_3 from GROUP_DEFINITIONS
)
MERGE GROUP_MAP gm
USING
    (
  SELECT am.CUST_ID, gd.GROUP_ID, am.START_DATE
  FROM ATTRIBUTE_MAP am 
  JOIN gd
  ON  am.ATTRIBUTE_ID = gd.ATTRIBUTE_ID  AND coalesce(am.VALUE, '') = coalesce(gd.VALUE, '')
  join (select GROUP_ID, count(*) as ATTR_COUNT from gd where ATTRIBUTE_ID is NOT NULL group by GROUP_ID) as gc
  on gd.GROUP_ID = gc.GROUP_ID
  GROUP BY am.CUST_ID, gd.GROUP_ID, am.START_DATE
  HAVING count(am.ATTRIBUTE_ID) = max(gc.ATTR_COUNT)
   ) src
    ON gm.GROUP_ID = src.GROUP_ID
       AND gm.CUST_ID = src.CUST_ID
    WHEN NOT MATCHED
     THEN -- create association in GROUP_MAP
     INSERT(CUST_ID,
           GROUP_ID,
           FROM_DATE) VALUES
                         (src.CUST_ID, src.GROUP_ID, src.START_DATE);

如果我正确理解了问题,这应该可以做到:

请注意,我使用了
GETDATE()
,因为我没有[START\u DATE]字段,但您需要在代码中替换它

样本数据:

CREATE TABLE #ATTRIBUTE_MAP(CUST_ID      INT,
                       ATTRIBUTE_ID INT,
                       VALUE        VARCHAR(20));

INSERT INTO #ATTRIBUTE_MAP
VALUES
      (50, 1, 'New York'),
      (50, 2, NULL);

CREATE TABLE #GROUP_DEFINITIONS(GROUP_ID    INT,
                          ATTRIBUTE_1 INT,
                          VALUE_1     VARCHAR(20),
                          ATTRIBUTE_2 INT,
                          VALUE_2     VARCHAR(20),
                          ATTRIBUTE_3 INT,
                          VALUE_3     VARCHAR(20));

INSERT INTO #GROUP_DEFINITIONS
VALUES
      (10, 1, 'New York', 2, NULL, NULL, NULL),
      (20, 2, NULL, NULL, NULL, NULL, NULL);

CREATE TABLE #GROUP_MAP(CUST_ID     INT,
                    GROUP_ID    INT,
                    [FROM_DATE] DATE);
查询:

MERGE #GROUP_MAP gm
USING
    (SELECT DISTINCT
           am.CUST_ID,
           CAST(GETDATE() AS DATE) AS [START_DATE], --<-- you will need to change this
           gd.GROUP_ID
     FROM   #ATTRIBUTE_MAP am
           INNER JOIN
                   (
                   SELECT GROUP_ID,
                        ATTRIBUTE_1 AS ATTRIBUTE_ID,
                        VALUE_1
                   FROM     #GROUP_DEFINITIONS
                   UNION ALL
                   SELECT GROUP_ID,
                        ATTRIBUTE_2,
                        VALUE_2
                   FROM     #GROUP_DEFINITIONS
                   UNION ALL
                   SELECT GROUP_ID,
                        ATTRIBUTE_3,
                        VALUE_3
                   FROM   #GROUP_DEFINITIONS) gd ON am.ATTRIBUTE_ID = gd.ATTRIBUTE_ID) src
    ON gm.GROUP_ID = src.GROUP_ID
       AND gm.CUST_ID = src.CUST_ID
    WHEN NOT MATCHED
     THEN -- create association in GROUP_MAP
     INSERT(CUST_ID,
           GROUP_ID,
           FROM_DATE) VALUES
                         (src.CUST_ID, src.GROUP_ID, src.START_DATE);
结果:


您能解释一下属性映射和组之间的关系吗_DEFINITIONS@KamranFarzami两者之间确实没有直接关系。属性映射将离散的属性/值映射到客户,而组定义更像是一个维度表-它只用于定义一个组。这有意义吗?属性映射记录必须匹配组定义记录中的所有属性,还是仅匹配其中的任何一个?是一个空的组\u定义。属性\ux]值为空,还是一个空字符串?am.START\u DATE的值是您需要考虑的,它是什么类型的。是日期还是日期时间。GROUP_MAP中的列DATE只是记录插入GROUP_MAP表时的时间戳?@radshop空属性为NULL。属性映射记录仅包含1个客户与1个属性的关联。如果客户有多个属性,则它们是单独的记录。如果分配给客户的属性满足组中的所有属性“条件”,则该客户将属于一个组。我可能错了,但在我看来,如果某些属性(但不是所有属性)匹配,则这将不正确地匹配客户和组。您的示例数据没有这种情况。@radshop请您完成以下内容并回复给我,我将测试您提到的情况:插入到#GROUP#u定义值(,,,)插入到#GROUP#u定义值(30,1,'纽约',5,'面包店',NULL,NULL)我明白您的意思,但从某种意义上说,它仍然是正确的,因为我们在该组中还有属性_1=1和值_1='newyork'。我只是使用@KamranFarzami中的设置代码来测试这个,它不起作用(开始时很匆忙),我现在没有时间处理它。我会稍后再查看。修复并测试了代码。我想它能满足你的需求。到目前为止,它似乎还在工作。我对语法有点困惑。为什么我们需要在这里合并:
coalesce(am.VALUE,”)=coalesce(gd.VALUE,”)
?@Ted您显示的示例数据具有空值,因此为了匹配这些值,我们将它们合并为一个空的非空值。拿出联合体,看看有什么不同——也许我误解了你的要求,所以不管用什么都可以。
SELECT CUST_ID , GROUP_ID , FROM_DATE
FROM   #GROUP_MAP;