1

我有一张这样的桌子:

我的桌子

我喜欢得到这样的东西:

我的结果表

以“属性”开头的行将转到属性列。以“Location”开头的行将转到“Location”列,以“error”开头的行将转到“ErrorMessage”列。此处的表包含类似父子的数据。例如,属性 X 的位置为“abc”,其中包含两个错误“1234”和“5678”。

根据到目前为止的评论,我正在添加更多信息。

Aaron Bertrand 问:Q1. 你可以绝对依赖 rowid 是顺序的吗?

A1.Rowid 是按顺序递增的,但并不总是以 1 的顺序递增。

让我们看一个例子。属性 X 从 rowid = 1 开始,属性 Y 从 8 开始。属性 X 的所有内容都在 rowid 1 到 7 之间。如果我们进入另一个级别,位置 abc 从 2 开始,“def”从 5 开始。位置“abc”的所有错误' 将在 rowid 3 到 4 之间。

Q2。对于任何位置/属性组合,是否只有一组数据?或者第 15 行是否有可能再次是属性 X,第 16 行又是属性 abc,等等?

A2。Property-Location 组合只有一组数据。因此,如果您在第 2 行找到属性 X - 位置 abc,您稍后将不会在桌子上找到它。

更多信息:此处的示例只有有限数量的行。实际表的行数比这多得多。

到目前为止,我使用 WHILE 循环确实得到了我的结果。我只是想知道是否有任何替代方法可以做到这一点而无需逐行进行。我正在使用 SQL 2008 R2。

4

5 回答 5

1

这可以在 1 个查询中完成。首先将数据分成三部分(属性、位置和错误)并确定父 ID。最后,使用常规连接来创建结果:

with P as (
  select ID, ColumnDesc 
  from MyTable P
  where columnDesc like 'Property %'
),
L as (
  select ID, ColumnDesc, (Select MAX(P.id) from P where P.ID<L.ID ) as ParentID 
  from MyTable L
  where columnDesc like 'Location %'
),
E as (
  select ID, ColumnDesc, (Select MAX(L.id) from L where L.ID<E.ID ) as ParentID 
  from MyTable E
  where columnDesc like 'error %'
)
select 
  P.ColumnDesc as Property,
  L.ColumnDesc as Location,
  E.ColumnDesc as Error
FROM p
JOIN L ON (L.ParentId = P.ID)
JOIN E ON (E.ParentID = L.ID)
ORDER BY P.ID, L.ID, E.ID
于 2013-11-14T19:31:12.213 回答
0
with ds as (
select 1 as rowid, 'Property X' as columnDesc
union
select 2 as rowid, 'Location abc' 
union
select 3 as rowid, 'error 1234' 
union
select 3 as rowid, 'error 3456' 
union
select 4 as rowid, 'Property Y' 
union
select 5 as rowid, 'Location abc' 
union
select 6 as rowid, 'error 1234' 
union
select 7 as rowid, 'Location def' 
union
select 8 as rowid, 'error 12' 


)

,

rnProperty as (
select row_number() over (order by rowid) as rn , * from ds
where
columnDesc like 'Property%'),

rnLocation as (
select row_number() over (order by rowid) as rn , * from ds
where
columnDesc like 'Location%')



select 
rn.columnDesc, rnL.columnDesc, ds2.columnDesc

from rnProperty rn 
left join rnProperty rn2 on rn2.rn = rn.rn + 1
left join rnLocation rnL on rnL.rowid > rn.rowid and rnL.rowid < isnull(rn2.rowId,100000)
left join rnLocation rnL2 on rnL2.rn = rnL.rn + 1
left join ds ds2 on ds2.rowid > rnL.rowid and ds2.rowid < isnull(rnL2.rowid,1000000) and ds2.columnDesc like 'error%'
于 2013-11-14T17:28:54.883 回答
0

我认为有趣的问题。这是Oracle中的解决方案。我认为这是迄今为止发布的最短的一个,仅使用一个带有两个子查询的查询。

WITH data1 AS
(
   SELECT 1 AS id,'Property X' AS columnDesc FROM DUAL
   UNION SELECT 2 AS id,'Location abc' FROM DUAL
   UNION SELECT 3 AS id,'error 1234' FROM DUAL
   UNION SELECT 4 AS id,'error 3456' FROM DUAL
   UNION SELECT 5 AS id,'Property Y' FROM DUAL
   UNION SELECT 6 AS id,'Location abc' FROM DUAL
   UNION SELECT 7 AS id,'error 1234' FROM DUAL
   UNION SELECT 8 AS id,'Location def' FROM DUAL
   UNION SELECT 9 AS id,'error 12'FROM DUAL
)
SELECT d2.columnDesc,d3.columnDesc,d.columnDesc
FROM data1 d, data1 d2, data1 d3
WHERE d.columnDesc NOT LIKE 'Property%'
AND d.columnDesc NOT LIKE 'Location%'
AND d2.id < d.id
AND d2.id = (SELECT max(id) FROM data1
             WHERE columnDesc LIKE 'Property%' AND id < d.id)
AND d3.id < d.id
AND d3.id = (SELECT max(id) FROM data1
             WHERE columnDesc LIKE 'Location%' AND id < d.id);
于 2013-11-14T18:31:25.273 回答
0

TSQL

WITH
source AS
(
  SELECT 1 AS id,'Property X' AS columnDesc
  UNION ALL SELECT 2 AS id,'Location abc'
  UNION ALL SELECT 3 AS id,'error 1234'
  UNION ALL SELECT 4 AS id,'error 3456'
  UNION ALL SELECT 5 AS id, 'Location def'
  UNION ALL SELECT 6 AS id,'error 1234'
  UNION ALL SELECT 7 AS id,'error 3456'
  UNION ALL SELECT 8 AS id,'Property Y'
  UNION ALL SELECT 9 AS id,'Location ab'
  UNION ALL SELECT 10 AS id,'error 12'
  UNION ALL SELECT 11 AS id,'error 56'
  UNION ALL SELECT 12 AS id,'Location de'
  UNION ALL SELECT 13 AS id,'error 12'
  UNION ALL SELECT 14 AS id,'error 56'
),
maxid AS
(
  SELECT MAX(id) as maxid FROM source
),
properties AS
(
  SELECT id, columnDesc FROM source WHERE columnDesc like 'Property%'
),
propertiesPlus AS
(
  SELECT id, columnDesc,
    isnull( (SELECT MIN(p2.id) FROM properties p2 WHERE p1.id < p2.id ),
    (SELECT maxid FROM maxid)) as nextid
  FROM properties p1
),
locations AS
(
  SELECT id, columnDesc FROM source WHERE columnDesc like 'Location%'
),
locationsPlus AS
(
  SELECT id, columnDesc,
    isnull( (SELECT MIN(l2.id) FROM locations l2 WHERE l1.id < l2.id ),
    (SELECT maxid FROM maxid)) as nextid
  FROM locations l1
),
errors AS
(
  SELECT id, columnDesc FROM source WHERE columnDesc like 'error%'
)
SELECT p.columnDesc as Property, l.columnDesc as Location, e.columnDesc as Error
FROM propertiesPlus p
  JOIN locationsPlus l ON l.id BETWEEN p.id and p.nextid
  JOIN errors e ON e.id BETWEEN l.id AND l.nextid
于 2013-11-14T18:53:48.483 回答
0

您可以获取所有'error %'行并使用columnDescas ErrorMessage,然后计算Property为给定行之前的最新columnDesc行并匹配掩码'Property %',对于Location. 这是我正在谈论的查询:

SELECT
  Property     = (SELECT TOP (1) columnDesc
                  FROM atable
                  WHERE rowid < main.rowid AND columnDesc LIKE 'Property %'
                  ORDER BY rowid DESC),
  Location     = (SELECT TOP (1) columnDesc
                  FROM atable
                  WHERE rowid < main.rowid AND columnDesc LIKE 'Location %'
                  ORDER BY rowid DESC),
  ErrorMessage = columnDesc
FROM atable AS main
WHERE columnDesc LIKE 'error %'
;
于 2013-11-15T09:47:01.430 回答