使用左连接重复行

时间:2016-11-13 02:10:46

标签: sql sql-server tsql

假设您有一个这样的表:

+----+--------+-------------+----------------+--------+
| Id | Parent | Description | NumberOfThings | Number |
+----+--------+-------------+----------------+--------+
| A  | NULL   | This is A   |              1 | NULL   |
| B  | NULL   | This is B   |              3 | NULL   |
| C  | NULL   | This is C   |              2 | NULL   |
+----+--------+-------------+----------------+--------+

并且您希望使用NumberOfThings来创建子项数:

+-----+--------+-------------+----------------+--------+
| Id  | Parent | Description | NumberOfThings | Number |
+-----+--------+-------------+----------------+--------+
| A   | NULL   | This is A   |              1 | NULL   |
| B   | NULL   | This is B   |              3 | NULL   |
| C   | NULL   | This is C   |              2 | NULL   |
| A-1 | A      | This is A   |              1 | 1      |
| B-1 | B      | This is B   |              1 | 1      |
| C-1 | C      | This is C   |              1 | 1      |
| B-2 | B      | This is B   |              1 | 2      |
| C-2 | C      | This is C   |              1 | 2      |
| B-3 | B      | This is B   |              1 | 3      |
+-----+--------+-------------+----------------+--------+

我该怎么做呢?我知道我可以使用LEFT JOIN和某种通配符ON子句,但我不知道从哪里开始。

这是使用SQL Server 2012,但我相信可以有一个特定于任何数据库引擎的解决方案。

SQL小提琴首次尝试:http://sqlfiddle.com/#!6/dcafc/2

3 个答案:

答案 0 :(得分:0)

看起来你正在寻找集合的联合加上集合与自身的交叉乘积。但是,鉴于NumberOfThings专栏的预期结果,我不确定这是否正确。

SELECT
    [Id]
    , [Parent]
    , [NumberOfThings]
FROM
    [dbo].[NumThings]
UNION ALL
SELECT
    A.[Id] + '-' + CAST(B.NumberOfThings AS VARCHAR(50))
    , B.[Id] As Parent
    , A.[NumberOfThings]
FROM
    [dbo].[NumThings] A
    , [dbo].[NumThings] B
GO

答案 1 :(得分:0)

这里.....我相信这是你正在寻找的结果:

     SELECT
         [Id]
          , [Parent]
          , [NumberOfThings]
      FROM
[dbo].[NumThings]
       UNION ALL
     SELECT
          A.[Id] + '-' + CAST(B.NumberOfThings AS VARCHAR(50))
           , A.[Id] As Parent
        , B.[NumberOfThings]
     FROM
         [dbo].[NumThings] A
     LEFT JOIN [dbo].[NumThings] B
         ON B.NumberOfThings BETWEEN 1 AND A.NumberOfThings
   GO

答案 2 :(得分:0)

这有点乱,但递归CTE可以做到这一点:

with cte as (
  select Id as BaseId,
         cast(Id as varchar(10)) as Id,
         cast(null as varchar(1)) as Parent,
         Description,
         NumberOfThings,
         NumberOfThings as TotalCount,
         1 as CurrentCount,
         null as Number
    from NumThings
   union all
  select c.BaseId,
         cast(c.BaseId + '-' + cast(c.CurrentCount as varchar(8)) as varchar(10)) as Id,
         c.BaseId as Parent,
         c.Description,
         1 as NumberOfThings,
         c.TotalCount,
         c.CurrentCount + 1 as CurrentCount,
         c.CurrentCount as Number
    from cte c
   where c.CurrentCount <= c.TotalCount
)
select Id,
       Parent,
       Description,
       NumberOfThings,
       Number
  from cte
 order by case when Parent is null then 0 else 1 end,
          Number,
          Id;

Demo