Нужна помощь с транзакцией SQL для сжатия данных в базе данных - PullRequest
0 голосов
/ 18 января 2019

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

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

Но моя транзакция SQL не работает.

[dataBase1].[dbo].[table1] имеет несколько сотен тысяч записей с несколькими столбцами (Name, Place, etc.).

[dataBase1].[dbo].[table2] содержит список уникальных имен из [table1] и заголовки для остальных столбцов (место и т. Д.), Которые пусты.

Я попробовал следующий код.

DECLARE @name varchar(max);
DECLARE @place varchar(max);

DECLARE db_cursor SCROLL CURSOR FOR 
     SELECT [Name] 
     FROM [dataBase1].[dbo].[table2];

OPEN HostName_cursor

FETCH NEXT FROM db_cursor INTO @name;

WHILE @@FETCH_STATUS = 0
BEGIN
     SELECT DISTINCT TOP(1) @place = [Place] 
     FROM [dataBase1].[dbo].[table1] 
     WHERE [Name] = @name 
       AND [Place] IS NOT NULL AND [Place] <> '' 
       AND (EXISTS  (SELECT [Place], COUNT (*) AS TOTAL 
                     FROM [dataBase1].[dbo].[table1] 
                     GROUP BY [Place])) 
     GROUP BY [Place];

     UPDATE [dataBase1].[dbo].[table2] 
     SET [Place] = @place 
     WHERE [Name] = @name;      

     SET @place = '';

     FETCH NEXT FROM db_cursor INTO @name
END
Столбец

[Place] для определенного уникального [Name] имеет 53 значений, а наибольшее количество повторяющихся значений равно 3 . По сути, я хочу автоматизировать следующую транзакцию SQL для каждой уникальной [Name].

SELECT DISTINCT TOP 1 
    [Place], COUNT (*) TOTAL 
FROM 
    [dataBase1].[dbo].[table1] 
WHERE 
    [Name] = 'xxxxxx' 
    AND [Place] IS NOT NULL AND [Place] <> '' 
GROUP BY [Place] 
ORDER BY TOTAL DESC;

1 Ответ

0 голосов
/ 18 января 2019

Это можно сделать как несколько шагов, каждое здание на следующем. Вы хотите работать со всеми именами и местами одновременно.

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

SELECT name, place, COUNT(place) as placecount
FROM table1
GROUP BY name, place

Теперь вам нужно найти тот, у кого наибольшее количество, и первый по алфавиту в случае связей. Вы можете сделать это, выполнив ROW_NUMBER по результатам вышеупомянутого, перезапустив счетчик (разделение) по имени и упорядочив по месту, а затем по месту для разрешения связей. Используя CTE (вы также можете сделать это как подзапрос), это выглядело бы как

WITH places as (
  SELECT name, place, COUNT(place) as placecount
  FROM table1
  GROUP BY name, place
)
SELECT name, place, ROW_NUMBER() OVER (PARTITION BY name ORDER BY placecount, place) as RN
FROM places

Если вы посмотрите на эти данные, то место, в котором вы хотите указать любое имя, должно быть в строке с RN, равным 1. Таким образом, вы можете получить окончательные данные, которые вы ищете, с помощью запроса, подобного этому

WITH places as (
  SELECT name, place, COUNT(place) as placecount
  FROM table1
  GROUP BY name, place
), orderplaces as (
  SELECT name, place, ROW_NUMBER() OVER (PARTITION BY name ORDER BY placecount, place) as RN
  FROM places
)
Select name, place
FROM orderplaces
WHERE RN = 1

Поскольку вы хотите обновить таблицу2 с помощью данных этого места, а не просматривать их, вы присоединитесь к таблице2 в последнем запросе и обновите что-то вроде этого

WITH places as (
  SELECT name, place, COUNT(place) as placecount
  FROM table1
  GROUP BY name, place
), orderplaces as (
  SELECT name, place, ROW_NUMBER() OVER (PARTITION BY name ORDER BY placecount, place) as RN
  FROM places
)
UPDATE T2 set place = OP.place
FROM orderplaces OP
   INNER JOIN table2 T2 on T2.name = OP.name
WHERE RN = 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...