SQL выберите MAX, чтобы найти одну запись группы - PullRequest
0 голосов
/ 21 марта 2012

У меня есть много записей, которые представляют одну и ту же информацию, но с разными ключами для других таблиц. Мне нужно сгруппировать эти записи по их общим атрибутам (Att1, Att2, Att3), а затем выбрать один RecordID из всех общих записей в качестве masterID для этих общих записей. Этот masterID необходимо добавить к каждой записи, которую он представляет, только если masterID равен нулю. Я не могу изменить структуру данных, и все значения таблицы являются GUID. Я пробовал MAX, но не получаю группировку.

TableA (Current State)

RecordID          Att1         Att2     Att3     MasterID
1                 A            B        C        
2                 A            B        C
3                 A            B        C
4                 D            E        F
5                 D            E        F
6                 D            E        F
7                 G            H        I         7
8                 G            H        I         7
9                 G            H        I         7

ОБНОВЛЕНИЕ: добавлен ожидаемый результат.

TableA (Expected Result)

RecordID          Att1         Att2     Att3     MasterID
1                 A            B        C        1
2                 A            B        C        1
3                 A            B        C        1
4                 D            E        F        4
5                 D            E        F        4
6                 D            E        F        4
7                 G            H        I        7
8                 G            H        I        7
9                 G            H        I        7

Ответы [ 4 ]

3 голосов
/ 21 марта 2012

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

Я считаю, что должно работать следующее (не зависит от поставщика):

UPDATE TableA as a SET masterId = (SELECT MIN(b.recordId) 
                                   FROM TableA as b
                                   WHERE b.att1 = a.att1
                                   AND b.att2 = a.att2
                                   AND b.att3 = a.att3)
WHERE masterId IS NULL

<ч /> РЕДАКТИРОВАТЬ:

При обнаружении, что GUID можно заказать, но нельзя передать за MIN() или MAX() (Что?) -

У вас есть (как минимум) три варианта:

  1. Приведите проводника к проходимому типу (то есть - SELECT MIN(CAST(b.recordId as CHAR(36)))). Тем не менее, это, вероятно, будет неэффективным, просто потому, что он будет приводить каждую строку (видите, именно поэтому для внутренних идентификаторов предпочтительнее быть простые целые числа).
  2. Попытка этого независимого от поставщика заявления:

    UPDATE TableA as a SET masterId = (SELECT b.recordId
                                       FROM TableA as b
                                       LEFT JOIN TableA as c
                                       ON c.att1 = b.att1
                                       AND c.att2 = b.att2
                                       AND c.att3 = b.att3
                                       AND c.recordId < b.recordId
                                       WHERE b.att1 = a.att1
                                       AND b.att2 = a.att2
                                       AND b.att3 = a.att3
                                       AND b.recordId <= a.recordId
                                       AND c.recordId IS NULL)
    WHERE masterId IS NULL
    
  3. Существует также более идиоматическая версия для SQL Server:

    UPDATE Updating
    SET Updating.masterId = Origin.recordId
    FROM TableA Updating
    JOIN (TableA Origin
          LEFT JOIN TableA Exclusion
                 ON Exclusion.att1 = Origin.att1
                    AND Exclusion.att2 = Origin.att2
                    AND Exclusion.att3 = Origin.att3
                    AND Exclusion.recordId < Origin.recordId) 
      ON Exclusion.recordId IS NULL
         AND Origin.att1 = Updating.att1
         AND Origin.att2 = Updating.att2
         AND Origin.att3 = Updating.att3
    WHERE Updating.masterId IS NULL
    

    Пример SQL Fiddle

1 голос
/ 21 марта 2012

Если вы хотите выбрать только тогда, вы можете использовать следующий запрос -

select recordid ,
       Att1,
       Att2,
       Att3,
       COALESCE( MasterID , (select min(a2.recordid) from tableA a2
                            where a2.Att1 = a1.Att1
                            and a2.Att2= a1.Att2
                            and a1.Att3 = a2.Att3))
from TableA a1
1 голос
/ 21 марта 2012

Попробуйте это:

UPDATE m
SET
    MasterID = s.RecordID
FROM TableA AS m
INNER JOIN (
    SELECT Att1, Att2, Att3, MIN(RecordID) AS RecordID          
    FROM TableA 
    GROUP BY Att1, Att2, Att3
) AS s
    ON m.Att1 = s.Att1 AND m.Att2 = s.Att2 AND m.Att3 = s.Att3
WHERE
    MasterID  IS NULL
0 голосов
/ 21 марта 2012

Вы можете использовать перекрестное применение, чтобы сделать выбор.При перекрестном применении в основном выбирается самый низкий RecordID, который имеет соответствующие Att1, Att2 и Att3, и присоединяется к RecordID в виде столбца с именем MasteRID.

WITH temp as (SELECT RecordID, Att1, Att2, Att3, c.MasterID FROM dbo.TableA b
    CROSS APPLY (SELECT TOP 1 RecordID as MasterID 
    FROM dbo.TableA a 
    WHERE a.Att1=b.Att1 
    AND a.Att2=b.Att2 AND a.Att3=b.Att3 
    ORDER BY RecordID) c)

UPDATE TableA 
SET MasterID=t.MasterID
FROM temp t
WHERE RecordID=t.RecordID

Обновление обновит столбец MasterID каждой записи RecordID с соответствующим RecordID.

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