我有一个必须维护的旧产品。该表之一类似于以下示例:
DECLARE @t TABLE
(
id INT,
DATA NVARCHAR(30)
);
INSERT INTO @t
SELECT 1,
'name: Jim Ey'
UNION ALL
SELECT 2,
'age: 43'
UNION ALL
SELECT 3,
'----------------'
UNION ALL
SELECT 4,
'name: Johnson Dom'
UNION ALL
SELECT 5,
'age: 34'
UNION ALL
SELECT 6,
'----------------'
UNION ALL
SELECT 7,
'name: Jason Thwe'
UNION ALL
SELECT 8,
'age: 22'
SELECT *
FROM @t;
/*
You will get the following result
id DATA
----------- ------------------------------
1 name: Jim Ey
2 age: 43
3 ----------------
4 name: Johnson Dom
5 age: 34
6 ----------------
7 name: Jason Thwe
8 age: 22
*/
现在,我想以以下形式获取信息:
name age
-------------- --------
Jim Ey 43
Johnson Dom 34
Jason Thwe 22
最简单的方法是什么?谢谢。
出于(略有病态)的好奇心,我试图提出一种方法来转换您提供的确切输入数据。
当然,更好的方法是正确地构造原始数据。对于旧系统,这可能是不可能的,但是可以创建ETL流程以将这些信息带到中间位置,这样就不必实时运行像这样的丑陋查询。
此示例假定所有ID都是一致且连续的(否则,ROW_NUMBER()
将需要使用其他列或新的Identity列来保证对ID进行正确的余数运算)。
SELECT
Name = REPLACE( Name, 'name: ', '' ),
Age = REPLACE( Age, 'age: ', '' )
FROM
(
SELECT
Name = T2.Data,
Age = T1.Data,
RowNumber = ROW_NUMBER() OVER( ORDER BY T1.Id ASC )
FROM @t T1
INNER JOIN @t T2 ON T1.id = T2.id +1 -- offset by one to combine two rows
WHERE T1.id % 3 != 0 -- skip delimiter records
) Q1
-- skip every other record (minus delimiters, which have already been stripped)
WHERE RowNumber % 2 != 0
这是一个更实际的示例,因为实际的ID值并不重要,仅行顺序无关紧要。
DECLARE @NumberedData TABLE( RowNumber INT, Data VARCHAR( 100 ) );
INSERT @NumberedData( RowNumber, Data )
SELECT
RowNumber = ROW_NUMBER() OVER( ORDER BY id ASC ),
Data
FROM @t;
SELECT
Name = REPLACE( N2.Data, 'name: ', '' ),
Age = REPLACE( N1.Data, 'age: ', '' )
FROM @NumberedData N1
INNER JOIN @NumberedData N2 ON N1.RowNumber = N2.RowNumber + 1
WHERE ( N1.RowNumber % 3 ) = 2;
DELETE @NumberedData;
同样,最好避免实时运行这样的查询,而使用计划的事务性ETL流程。以我的经验,像这样的半结构化数据容易出现html" target="_blank">异常。
尽管示例#1和#2(以及其他人提供的解决方案)展示了处理数据的巧妙方法,但转换该数据的更实用的方法是使用游标。为什么?它实际上可能会执行得更好(没有嵌套查询,递归,数据透视或行编号),即使它比较慢,也为错误处理提供了更好的机会。
-- this could be a table variable, temp table, or staging table
DECLARE @Results TABLE ( Name VARCHAR( 100 ), Age INT );
DECLARE @Index INT = 0, @Data VARCHAR( 100 ), @Name VARCHAR( 100 ), @Age INT;
DECLARE Person_Cursor CURSOR FOR SELECT Data FROM @t;
OPEN Person_Cursor;
FETCH NEXT FROM Person_Cursor INTO @Data;
WHILE( 1 = 1 )BEGIN -- busy loop so we can handle the iteration following completion
IF( @Index = 2 ) BEGIN
INSERT @Results( Name, Age ) VALUES( @Name, @Age );
SET @Index = 0;
END
ELSE BEGIN
-- optional: examine @Data for integrity
IF( @Index = 0 ) SET @Name = REPLACE( @Data, 'name: ', '' );
IF( @Index = 1 ) SET @Age = CAST( REPLACE( @Data, 'age: ', '' ) AS INT );
SET @Index = @Index + 1;
END
-- optional: examine @Index to see that there are no superfluous trailing
-- rows or rows omitted at the end.
IF( @@FETCH_STATUS != 0 ) BREAK;
FETCH NEXT FROM Person_Cursor INTO @Data;
END
CLOSE Person_Cursor;
DEALLOCATE Person_Cursor;
我创建了100K行的示例源数据,上面提到的三个示例对于转换数据似乎大致等效。
我创建了一百万行源数据,并且与以下类似的查询为选择行的子集(例如在网页或报表中的网格中使用)提供了出色的性能。
-- INT IDENTITY( 1, 1 ) numbers the rows for us
DECLARE @NumberedData TABLE( RowNumber INT IDENTITY( 1, 1 ), Data VARCHAR( 100 ) );
-- subset selection; ordering/filtering can be done here but it will need to preserve
-- the original 3 rows-per-result structure and it will impact performance
INSERT @NumberedData( Data )
SELECT TOP 1000 Data FROM @t;
SELECT
N1.RowNumber,
Name = REPLACE( N2.Data, 'name: ', '' ),
Age = REPLACE( N1.Data, 'age: ', '' )
FROM @NumberedData N1
INNER JOIN @NumberedData N2 ON N1.RowNumber = N2.RowNumber + 1
WHERE ( N1.RowNumber % 3 ) = 2;
DELETE @NumberedData;
我看到100万条记录的执行时间为4-10毫秒(i7-3960x)。
问题内容: 在Ubuntu中,我想在Java 5和Java 6之间来回切换我的JAVA_HOME环境变量。 我打开一个终端并输入以下内容来设置JAVA_HOME环境变量: 在同一终端窗口中,键入以下内容以检查环境变量是否已更新: 而且我看到了 /usr/lib/jvm/java-1.5.0-sun ,这是我期望看到的。另外,我修改〜/ .profile并将JAVA_HOME环境变量设置为/usr/
问题内容: 我有一个表,其数据对的建模如下: 然后总是更大。这些对表示要进行的替换。因此,将100替换为50,然后将50替换为40,然后将其替换为10。 因此结果将是这样的: 有没有一种我可以更改或加入此表来表示的简洁方法? 我知道我可以自己加入类似于以下内容的内容: 但是,这需要多次通过,因此,为什么我问是否有更好的方法来完成它? 问题答案: 结果:
问题内容: 我正在为下面的用例设计Cassandra列族模式。.我不确定为下面的用例设计cassandra列族的最佳方法是什么?我将为此使用CQL Datastax Java驱动程序。 以下是我的用例和我现在设计的示例架构- 现在我将从上表中看到的是这样的- 每当我的应用程序运行时,我都会第一次要求上表中的所有内容。这意味着要给我上表中的所有内容。 然后每隔5或10分钟,我的后台线程就会检查该表,
问题内容: 我有以下匿名实现。 IntelliJ建议我将其替换为lambda表达式。例如: 使用单个语句时,语法为: 我可以使用什么快捷方式进行转换? 问题答案: 让IntelliJ在这里完成工作;您可以调用+ (或在Mac上为+ )以允许IntelliJ用lambda表达式替换它。
问题内容: 如何将的列表转换为单个字符串,例如: 变 变 …等等… 问题答案: 等于,所以返回。 通过字符串将序列中的所有项目连接起来,例如, ‘foo,bar,,baz’ 请注意,只能连接字符串序列。它不会自动调用。 因此,我们需要首先将所有项目都放入字符串中。
问题内容: 我正在使用UCanAccess JDBC驱动程序(版本3.0.3.1)连接到mdb文件。我需要将该列添加到现有表中。问题是该语句 引发异常: 似乎没有新版本的UCanAccess。 在这种情况下我该怎么办?由于多种原因,我不想使用ODBC驱动程序(在此进行说明- 从不使用ODBC的Java中操作Access数据库) 我看到的唯一解决方案是创建表的副本(例如TEmployeeBackup