【问题标题】:Need assistance with SQL transaction to condense data in a database需要 SQL 事务协助以在数据库中压缩数据
【发布时间】:2019-01-18 00:55:55
【问题描述】:

我正在尝试将数据压缩到一个数据库表中,该表包含多个具有不同列数据的唯一记录实例。

我想为每个列选择出现的最高值 特定的唯一记录

但我的 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。本质上,我想为每个唯一的[Name] 自动执行以下 SQL 事务。

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;

【问题讨论】:

  • 注意:DISTINCT + GROUP BY 没有意义。删除 DISTINCT。此外,您的查询不关心关系。如果多个位置具有相同的最大计数怎么办?它会随机选择一个。
  • 按照你的代码我猜这是 SQL Server。我会换标签。您能否确定 SQL Server 的确切版本,编辑标签并添加它。
  • 如果有平局,按字母顺序选择第一个。
  • 我使用的是 SQL Server 2017。

标签: sql sql-server sqltransaction


【解决方案1】:

这可以通过多个步骤来完成,每个步骤都建立在下一个步骤上。您想同时处理所有名称和地点。

首先,您要计算每个名称、地点组合的数量,因此按名称和地点分组,然后计算地点。您的查询将如下所示

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

由于您想使用此地点数据而不是查看它来更新 table2,因此您将在最终查询中加入 table2 并更新,类似这样

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;

【讨论】:

    猜你喜欢
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    相关资源
    最近更新 更多