Выберите две строки в одну - PullRequest
0 голосов
/ 11 октября 2019

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

+------------+--------+------+------------+--------------+--------------+------------+
|    Date    |  Time  | Acct |    Name    |   EmailOld   |   EmailNew   | ChangeType |
+------------+--------+------+------------+--------------+--------------+------------+
| 2019-10-11 | 8:05AM | 1234 | John Smith |              | John@new.com | INSERT     |
| 2019-10-11 | 8:04AM | 1234 | John Smith | John@old.com |              | DELETE     |
+------------+--------+------+------------+--------------+--------------+------------+

, который я хотел бы объединить в один результат, подобный этому:

+------------+--------+------+------------+--------------+--------------+------------+
|    Date    |  Time  | Acct |    Name    |   EmailOld   |   EmailNew   | ChangeType |
+------------+--------+------+------------+--------------+--------------+------------+
| 2019-10-11 | 8:05AM | 1234 | John Smith | John@old.com | John@new.com | UPDATE     |
+------------+--------+------+------------+--------------+--------------+------------+

Я пытался построить это: Две строки в одну строку в SQL

и это: Форматирование двух строк в одну строку

Но они имеют дело с числовыми значениями и не будут работать для моей ситуации.

Вот как выглядит мой SQL при извлечении из базы данных:

SELECT Date, Time, Acct, Name, EmailOld, EmailNew,
CASE
WHEN EmailOld = '' AND EmailNew <> '' THEN 'INSERT'
WHEN EmailOld <> '' AND EmailNew = '' THEN 'DELETE'
ELSE 'UPDATE'
END AS ChangeType,
ROW_NUMBER() OVER(PARTITION BY Acct ORDER BY Date, Time) AS RowNum
FROM EmailChanges

Ответы [ 3 ]

0 голосов
/ 11 октября 2019

Проблема здесь в том, как все записывается в таблицу EmailChanges. Для этих записей я бы предположил, что транзакции были реализованы следующим образом:

  • Электронная почта удалена, строка обновлена ​​
  • Новая электронная почта добавлена, строка обновлена.

Теперь я должен сделать некоторые предположения, чтобы понять это. Я должен предположить, что электронные письма хранятся в отдельной таблице, с одной строкой для каждого электронного письма, и для исторических целей вы помечаете старый адрес электронной почты как удаленный (вместо того, чтобы фактически удалить запись электронной почты), когда вы меняете адрес электронной почты,затем немедленно добавив новый адрес электронной почты. Это хороший шаблон, позволяющий отслеживать адреса электронной почты и изменения адресов для клиентов.

Однако, если ведение журнала выполняется с помощью триггера, этот шаблон возникает, поскольку были выполнены две отдельные операции. ,(Если эта регистрация ведется программно, измените способ регистрации обновлений программы.)

Как я уже говорил, я делаю предположения, но они являются разумными предположениями для ситуации, описанной выше. Чтобы вместо этого превратить их в ОБНОВЛЕНИЕ, у вас есть несколько разных методов, но ни один из них не обязательно правильно запишет обновление - кроме одного. Метод, который я бы использовал, состоял бы в том, чтобы создать триггер INSTEAD OF для ОБНОВЛЕНИЯ до адреса электронной почты. В рамках одной транзакции это пометит старый адрес электронной почты как УДАЛЕНО, добавит новую запись адреса электронной почты и зарегистрирует транзакцию UPDATE в таблице. Затем вместо двух отдельных вызовов для обновления адреса электронной почты (UPDATE ... SET Deleted, INSERT) ваш код выполняет одно действие (UPDATE), а затем триггер INSTEAD OF обрабатывает детали.

0 голосов
/ 11 октября 2019

Проверьте это-

SELECT [Date],[Time],Acct, [Name],EmailOld,EmailNew,
CASE
WHEN EmailOld <> '' AND EmailNew <> '' AND EmailOld<>EmailNew THEN 'UPDATE'
WHEN EmailOld = '' AND EmailNew <> '' THEN 'INSERT'
WHEN EmailOld <> '' AND EmailNew = '' THEN 'DELETE'
END AS ChangeType FROM 
(
SELECT [Date], MAX([Time]) AS [Time], Acct, [Name],
LTRIM(RTRIM(STRING_AGG(EmailOld,''))) AS EmailOld,LTRIM(RTRIM(STRING_AGG(EmailNew,''))) AS EmailNew
FROM EmailChanges
GROUP BY [Date],Acct,[Name]
) T;
0 голосов
/ 11 октября 2019

Вы можете попробовать это

with ins as (
select * from YourTable where ChangeType = 'INSERT'
)
, del as (
select * from YourTable where ChangeType = 'DELETE'
)
select Date, Time, Acct, Name
, EmailOld = iif(ins.EmailOld = '', del.EmailOld, ins.EmailOld)
, EmailNew = iif(ins.EmailNew = '', del.EmailNew, ins.EmailNew)
, ChangeType = 'UPDATE'
from ins 
    inner join del on del.Acct = ins.Acct
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...