Генерация идентификатора на основе значений столбца - PullRequest
3 голосов
/ 27 марта 2012

У меня есть следующий набор данных, представляющий сопоставление между проектом и деятельностью:

ProjectID  ActivityID
A         A
B         B
B         C
D         D
E         D
M         N

Я хотел бы рассчитать идентификатор на основе следующих правил:

a project that maps 1-1 with an activity:
A - A
M - N

one project that maps to multiple activities:
B - B
B - C

one activity that maps to multiple projects:
D - D
E - D

Это приведет к:

ProjectID  Activity CalculatedID
A         A        1
B         B        2
B         C        2
D         D        3
E         D        3
M         N        4

Я надеюсь, что там достаточно информации, любые идеи приветствуются.Я особенно заинтересован в разработке подхода, основанного на множествах.

- ОБНОВЛЕНИЕ: обратите внимание на ответы - я бы описал подход, использованный @Erwin, как классификацию отображений, в отличие отрешение, предоставляемое @mellamokb (которое основано на решении @ CodeByMoonlight), которое присваивает последовательный идентификатор.Оба ваших решения помогли мне в пути, спасибо, ребята!

Ответы [ 3 ]

2 голосов
/ 27 марта 2012

Вот решение, основанное на ответе @CodeByMoonlight, в котором рассматривается случай, когда чередование ActivityID и projectID может чередоваться, т. Е. Идентификатор ActivityID имеет более высокий идентификатор, чем некоторые другие записи, но ID проекта имеет более низкий идентификатор, чем некоторые другие записи:

SELECT
    D.ProjectID,
    D.ActivityID,
    -- generate id based on the three different scenarios
    -- 1) projects with 1-many activities, use project id
    -- 2) activities with 1-many projects, use activity id
    -- 3) 1-1, use project id
    DENSE_RANK() over (order by
        case
            when P.ProjectID is not null then P.ProjectID
            when A.ActivityID is not null then A.ActivityID
            else D.ProjectID
        end
    ) as Identifier
from
    MyTable D
left join
(
    -- projects with 1-many activities
    SELECT ProjectID
    FROM MyTable
    group by ProjectID
    having Count(ActivityID) > 1
) P on P.ProjectID = D.ProjectID
left join
(
    -- activities with 1-many projects
    SELECT ActivityID
    FROM MyTable
    group by ActivityID
    having Count(ProjectID) > 1
) A on A.ActivityID = D.ActivityID

Пример ввода:

B   C
A   A
B   B
B   G
D   D
B   F
E   D
M   N

Пример вывода:

A   A   1
B   B   2
B   G   2
B   F   2
B   C   2
E   D   3
D   D   3
M   N   4
2 голосов
/ 27 марта 2012

Это немного запутанно, но это работает:

SELECT ProjectID, ActivityID,
DENSE_RANK() OVER(ORDER BY ProjectID) +
DENSE_RANK() OVER(ORDER BY ActivityID) -
ROW_NUMBER() OVER(ORDER BY ProjectID, ActivityID) AS CalculatedID
FROM MyTable

Два применения DENSE_RANK создают эффект смещения против ROW_NUMBER при повторении ProjectID или ActivityID.

1 голос
/ 27 марта 2012
;WITH p AS (
    SELECT ProjectID FROM tbl GROUP BY ProjectID HAVING count(*) > 1
    ),a AS (
    SELECT ActivityID FROM tbl GROUP BY ActivityID HAVING count(*) > 1
    )
SELECT t.*
      ,CASE
         WHEN p.ProjectID  IS NOT NULL
          AND a.ActivityID IS NOT NULL THEN 4 -- n:m (missing in question!)
         WHEN p.ProjectID  IS NOT NULL THEN 2 -- 1:n
         WHEN a.ActivityID IS NOT NULL THEN 3 -- n:1
         ELSE                               1 -- 1:1
       END AS CalculatedID
FROM   tbl AS t
LEFT   JOIN p ON p.ProjectID = t.ProjectID
LEFT   JOIN a ON a.ActivityID = t.ActivityID

Объясните:

  • 1) В CTE p найдите все проекты, имеющие более одного вида деятельности.
  • 2) В CTE a найдите все действиякоторые имеют более одного проекта.
  • 3) ВЛЕВО СОЕДИНЯЙТЕ выводы к базовой таблице и различайте 4 случая в операторе CASE.

Я добавил случай 4 (n: m), который отсутствует в вопросе.
См. Рабочую демонстрацию для данных. SE .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...