Массовое обновление таблицы из строк из другой таблицы - PullRequest
8 голосов
/ 26 сентября 2008

2 таблицы:

Employees
- EmployeeID
- LeadCount


Leads
- leadID
- employeeID

Я хочу обновить столбец Employees.LeadCount, посчитав количество отведений в таблице Leads, имеющих одинаковые EmployeeID.

Примечание. Может быть более одного отведения с одним и тем же employeeID, поэтому я должен сделать DISTINCT(SUM(employeeID)).

Ответы [ 5 ]

12 голосов
/ 26 сентября 2008
UPDATE
    Employees E
SET
    E.LeadCount = (
        SELECT COUNT(L.EmployeeID)
        FROM Leads L
        WHERE L.EmployeeID = E.EmployeeID
    )
9 голосов
/ 26 сентября 2008

Вы настраиваете себя на проблему синхронизации данных. Поскольку строки в таблице Leads вставляются, обновляются или удаляются, необходимо постоянно обновлять столбец Employees.LeadCount.

Лучшим решением было бы вообще не хранить столбец LeadCount, а пересчитать количество отведений с помощью сводного запроса SQL, если вам нужно это значение. Таким образом, это всегда будет правильно.

SELECT employeeID, COUNT(leadId) AS LeadCount
FROM Leads
GROUP BY employeeID;

Другим решением является создание триггеров в таблице Leads для INSERT, UPDATE и DELETE, чтобы вы всегда поддерживали актуальность столбца Employees.LeadCount. Например, используя синтаксис триггера MySQL:

CREATE TRIGGER leadIns AFTER INSERT ON Leads
FOR EACH ROW BEGIN
  UPDATE Employees SET LeadCount = LeadCount + 1 WHERE employeeID = NEW.employeeID;
END

CREATE TRIGGER leadIns AFTER UPDATE ON Leads
FOR EACH ROW BEGIN
  UPDATE Employees SET LeadCount = LeadCount - 1 WHERE employeeID = OLD.employeeID;
  UPDATE Employees SET LeadCount = LeadCount + 1 WHERE employeeID = NEW.employeeID;
END

CREATE TRIGGER leadIns AFTER DELETE ON Leads
FOR EACH ROW BEGIN
  UPDATE Employees SET LeadCount = LeadCount - 1 WHERE employeeID = OLD.employeeID;
END

Другой вариант, если вы используете MySQL, это использовать синтаксис UPDATE для нескольких таблиц. Это расширение MySQL для SQL, оно не переносимо на другие марки RDBMS. Сначала сбросьте LeadCount во всех строках на ноль, затем выполните объединение с таблицей Leads и увеличьте LeadCount в каждой строке, созданной объединением.

UPDATE Employees SET LeadCount = 0;
UPDATE Employees AS e JOIN Leads AS l USING (employeeID)
  SET e.LeadCount = e.LeadCount+1;
4 голосов
/ 26 сентября 2008

Объединения работают одинаково для обновлений (и удалений) так же, как и для выборок (редактирование: в некоторых популярных СУБД, по крайней мере *):

UPDATE Employees SET
  LeadCount = Leads.LeadCount
FROM Employee
JOIN (
  SELECT EmployeeId, COUNT(*) as LeadCount 
  FROM Leads 
  GROUP BY EmployeeId
) as Leads ON
  Employee.EmployeeId = Leads.EmployeeId  

SUM (DISTINCT EmployeeId) не имеет смысла - вам просто нужен COUNT (*).

  • MS SQL Server поддерживает синтаксис UPDATE ... FROM и DELETE ... FROM , как и MySql , но стандарт SQL-92 поддерживает не. SQL-92 заставил бы вас использовать выражение строки. Я знаю, что DB2 поддерживает этот синтаксис, но не уверен ни в каком другом. Честно говоря, я нахожу сбивающую с толку версию SQL-92, но стандарты и теоретические аргументы будут утверждать, что синтаксис FROM нарушает реляционную теорию и может привести к непредсказуемым результатам с неточными предложениями JOIN или при переключении поставщиков СУБД.
1 голос
/ 26 сентября 2008
UPDATE Employees SET LeadCount = (
  SELECT Distinct(SUM(employeeID)) FROM Leads WHERE Leads.employeeId = Employees.employeeId
)
0 голосов
/ 26 сентября 2008

Стали сверху и удаляли зависимый подзапрос.

// create tmp -> TBL (EmpID, count)

insert into TBL 
   SELECT employeeID COUNT(employeeID) Di
   FROM Leads WHERE Leads.employeeId = Employees.employeeId GROUP BY EmployeeId
UPDATE Employees SET LeadCount = (
  SELECT count FROM TBL WHERE TBL.EmpID = Employees.employeeId
)

// drop TBL

РЕДАКТИРОВАТЬ Это "группа By", а не "отчетливый": b (спасибо Марку Брэкетту)

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