«Поворотные» неагрегированные данные в SQL Server - PullRequest
6 голосов
/ 19 ноября 2010

это будет первый вопрос, который я разместил здесь, так что извините за любые непреднамеренные ошибки в этикете доски.

В моем текущем проекте я взял большую ненормализованную таблицу и разбил ее на четыреотдельные, нормализованные таблицы.Моя конечная цель, к которой я обращаюсь к этой доске, - создать представление, которое имитирует ненормализованную таблицу для обратной совместимости.

Чтобы предоставить упрощенный снимок моего сценария, суть того, что я 'Я пытаюсь сделать ложь в двух таблицах:

ASSOC_ROLE          ASSOCIATE
----------          ----------
assoc_id (fk)       assoc_id (pk)
role_id  (fk)       last_name
org_nbr  (fk)

Так что, если я выдам следующий запрос ...

SELECT Assoc_Role.org_nbr, Assoc_Role.assoc_id, Associate.last_name, Assoc_Role.role_id
FROM Assoc_Role INNER JOIN
     Associate ON Assoc_Role.assoc_id = Associate.assoc_id
WHERE Assoc_Role.org_nbr = '1AA'

... Я получу следующий набор результатов

org_nbr     assoc_id     last_name     role_id
-------     --------     ---------     -------
1AA         1447         Cooper        1
1AA         1448         Collins       3
1AA         1448         Collins       4
1AA         1448         Collins       5
1AA         1449         Lynch         6

В конечном счете, представление, которое я хотел бы построить, выглядело бы примерно так:

org_nbr   role1_ID   role1_name   role2_ID   role2_name   role3_ID   role3_name   role4_ID   role4_name   role5_ID   role5_name   role6_ID   role6_name
-------   --------   ----------   --------   ----------   --------   ----------   --------   ----------   --------   ----------   --------   ----------
1AA       1447       Cooper       NULL       NULL         1448       Collins      1448       Collins      1448       Collins      1449       Lynch

Сначала я пытался использовать команду PIVOT, но, насколько я понимаю, PIVOT требует какой-тоагрегации, и это не соответствует моему сценарию.Я также поэкспериментировал с командой CASE в предложении SELECT, но это не сводит мой результат к одной записи.

Надеюсь, кто-то сможет пролить свет на то, как я могу это сделать.Дайте мне знать, если кому-то нужна дополнительная информация.Спасибо!

Скот

Ответы [ 2 ]

2 голосов
/ 19 ноября 2010

Если вы можете, я очень рекомендую делать этот тип поворота в обычном коде (c #, vb, что угодно).

PIVOTing на сервере SQL имеет много недостатков. Во-первых, все, что превышает 7 или 8 элементов, значительно увеличит время, затрачиваемое на ваши запросы. Во-вторых, вам нужно либо выполнить динамический sql, либо заранее узнать все потенциальные идентификаторы. В-третьих, его будет сложно поддерживать.

Те же проблемы существуют в ответе AakashM.

Мы пробовали много разных способов сделать эту работу в чистом SQL-параметре. Для небольших наборов данных с очень ограниченным кругом это будет работать просто отлично. Однако количество идентификаторов ролей у вас уже есть.

Вместо этого просто возьмите данные и на вашем любимом языке создайте нужную таблицу. В этот момент либо поместите данные в другую таблицу sql, либо отправьте их туда, куда они должны идти.

2 голосов
/ 19 ноября 2010

Чтобы получить основные данные нумерованных ролей, мы могли бы начать с

SELECT
    org_nbr
    , r1.assoc_id   role1_ID
    , r1.last_name  role1_name
    , r2.assoc_id   role2_ID
    , r2.last_name  role2_name
    , r3.assoc_id   role3_ID
    , r3.last_name  role3_name
    , r4.assoc_id   role4_ID
    , r4.last_name  role4_name
    , r5.assoc_id   role5_ID
    , r5.last_name  role5_name
    , r6.assoc_id   role6_ID
    , r6.last_name  role6_name
FROM
    ASSOC_ROLE ar
    LEFT JOIN ASSOCIATE r1 ON ar.role_id = 1 AND ar.assoc_id = r1.assoc_id
    LEFT JOIN ASSOCIATE r2 ON ar.role_id = 2 AND ar.assoc_id = r2.assoc_id
    LEFT JOIN ASSOCIATE r3 ON ar.role_id = 3 AND ar.assoc_id = r3.assoc_id
    LEFT JOIN ASSOCIATE r4 ON ar.role_id = 4 AND ar.assoc_id = r4.assoc_id
    LEFT JOIN ASSOCIATE r5 ON ar.role_id = 5 AND ar.assoc_id = r5.assoc_id
    LEFT JOIN ASSOCIATE r6 ON ar.role_id = 6 AND ar.assoc_id = r6.assoc_id

НО это даст нам для каждого org_nbr отдельную строку для каждого role_id, в котором есть данные! Что не то, что мы хотим - поэтому нам нужно GROUP BY org_nbr. Но тогда нам нужно либо GROUP BY, либо агрегировать по каждому столбцу в списке SELECT! Хитрость заключается в том, чтобы придумать агрегатную функцию, которая будет успокаивать SQL Server , а даст нам желаемые результаты. В этом случае MIN выполнит работу:

SELECT
    org_nbr
    , MIN(r1.assoc_id)   role1_ID
    , MIN(r1.last_name)  role1_name
    , MIN(r2.assoc_id)   role2_ID
    , MIN(r2.last_name)  role2_name
    , MIN(r3.assoc_id)   role3_ID
    , MIN(r3.last_name)  role3_name
    , MIN(r4.assoc_id)   role4_ID
    , MIN(r4.last_name)  role4_name
    , MIN(r5.assoc_id)   role5_ID
    , MIN(r5.last_name)  role5_name
    , MIN(r6.assoc_id)   role6_ID
    , MIN(r6.last_name)  role6_name
FROM
    ASSOC_ROLE ar
    LEFT JOIN ASSOCIATE r1 ON ar.role_id = 1 AND ar.assoc_id = r1.assoc_id
    LEFT JOIN ASSOCIATE r2 ON ar.role_id = 2 AND ar.assoc_id = r2.assoc_id
    LEFT JOIN ASSOCIATE r3 ON ar.role_id = 3 AND ar.assoc_id = r3.assoc_id
    LEFT JOIN ASSOCIATE r4 ON ar.role_id = 4 AND ar.assoc_id = r4.assoc_id
    LEFT JOIN ASSOCIATE r5 ON ar.role_id = 5 AND ar.assoc_id = r5.assoc_id
    LEFT JOIN ASSOCIATE r6 ON ar.role_id = 6 AND ar.assoc_id = r6.assoc_id
GROUP BY
    org_nbr

Выход:

org_nbr    role1_ID    role1_name role2_ID    role2_name role3_ID    role3_name role4_ID    role4_name role5_ID    role5_name role6_ID    role6_name
---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ----------
1AA        1447        Cooper     NULL        NULL       1448        Collins    1448        Collins    1448        Collins    1449        Lynch
Warning: Null value is eliminated by an aggregate or other SET operation.

Конечно, этого не хватит, если максимум role_id увеличится ...

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