合并存在定义的位置

时间:2016-03-01 17:56:11

标签: sql tsql

我有三张桌子,我在这里工作。 ATTRIBUTE_MAPGROUP_DEFINITIONSGROUP_MAP

ATTRIBUTE_MAP包含CUST_ID和关联的ATTRIBUTE_ID

GROUP_DEFINITIONS定义了一个群组。其列为GROUP_IDATTRIBUTE_1VALUE_1ATTRIBUTE_2VALUE_2ATTRIBUTE_3VALUE_3一个组由1到1组成带有值的3个属性。例如,属性可以是“State”,其值为“New York”。对于像'Owns Car'这样的布尔值,值也可以为null。

GROUP_MAP只是将CUST_ID映射到GROUP_ID

现在,我正在尝试编写一个脚本,查看ATTRIBUTE_MAP并查看客户是否属于GROUP_DEFINITIONS中定义的一个组。如果他(客户)这样做,则使用GROUP_MAPCUST_ID将行插入/更新到GROUP_ID。我遇到问题的部分是匹配属性值。

这是我到目前为止所做的:

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语句才能加入ATTRIBUTE_MAPPEER_GROUP_DEFINTIONS,然后从那里开始。任何帮助/建议将不胜感激。

以下是一个参考示例:

ATTRIBUTE_MAP

+---------+--------------+------------+ | CUST_ID | ATTRIBUTE_ID | VALUE | +---------+--------------+------------+ | 50 | 1 | 'New York' | +---------+--------------+------------+ | 50 | 2 | | +---------+--------------+------------+

GROUP_DEFINITIONS

+----------+-------------+------------+-------------+---------+-------------+---------+ | GROUP_ID | ATTRIBUTE_1 | VALUE_1 | ATTRIBUTE_2 | VALUE_2 | ATTRIBUTE_3 | VALUE_3 | +----------+-------------+------------+-------------+---------+-------------+---------+ | 10 | 1 | 'New York' | 2 | | | | +----------+-------------+------------+-------------+---------+-------------+---------+ | 20 | 2 | | | | | | +----------+-------------+------------+-------------+---------+-------------+---------+

所以脚本应该生成(在GROUP_MAP中):

+---------+----------+--------+ | CUST_ID | GROUP_ID | DATE | +---------+----------+--------+ | 50 | 10 | *date* | +---------+----------+--------+ | 50 | 20 | *date* | +---------+----------+--------+

2 个答案:

答案 0 :(得分:1)

我可能完全离开,但看起来你的内心选择需要像这样。如果我了解您要执行的操作,则会返回一个唯一的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);

答案 1 :(得分:1)

如果我理解了问题,应该这样做:

请注意我已使用GETDATE(),因为我没有[START_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);

QUERY:

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);

验证结果:

SELECT CUST_ID , GROUP_ID , FROM_DATE
FROM   #GROUP_MAP;

结果:

enter image description here