基于条件将Rowdata转换为多行

时间:2018-05-01 11:33:47

标签: sql sql-server sql-server-2008

我正在尝试根据日期

从单个列中提取父和子ID
     Cust_id     ID       Date 

    75407014    603    2018-04-27 
    79807014    603    2018-04-30 
    75407016    604    2018-04-23 
    79807016    604    2018-04-30 
    75407018    605    2018-04-24 
    79807018    605    2018-04-30 
    75407020    606    2018-04-24 
    79807020    606    2018-04-30 
    75407014    608    2018-04-27 

我想排除id = 608,因为只有一行,我的执行输出引用父和子id

Select Row_number () over (partition by Cust_id, id order by date ) rn 

我的预期输出:

Parent_id  Child_id 
75407014   79807014
75407016   79807016
75407018   79807018
75407020   79807020

因此,第一个日期的Cust_id将是parent_id,下一个日期将是child_id.ID是customer_id的公共链接列

非常感谢你的帮助

5 个答案:

答案 0 :(得分:1)

您可以使用row_number()功能

with t as (
 select *,
       row_number() over (partition by id order by date) Seq 
 from table t
 where exists (select 1 from table where id = t.id group by id having count(*) > 1)
)

select (case when seq = 1 then Cust_id end) Parent_id,
       (case when seq = 2 then Cust_id end) Child_id   
from t
where seq in (1,2);

答案 1 :(得分:1)

您可以leadpartition by id一起使用以获得所需的输出。

对于SQL Server 2012及更高版本

select * 
from   (select [cust_id], 
               lead([cust_id]) 
                 over(partition by id order by date) as Child_id 
        from   tablename t1)t 
where  child_id is not null 

<强> DEMO

<强>输出

+----------+----------+
| Cust_id  | Child_id |
+----------+----------+
| 75407014 | 79807014 |
+----------+----------+
| 75407016 | 79807016 |
+----------+----------+
| 75407018 | 79807018 |
+----------+----------+
| 75407020 | 79807020 |
+----------+----------+

对于旧版本的SQL Server ,您可以使用子查询查找如下所示的潜在客户。

select * 
from   (select [cust_id], 
               (select top 1 [cust_id] 
                from   tablename t2 
                where  t2.id = t1.id 
                       and t2.date > t1.date 
                order  by t2.date) as Child_id 
        from   tablename t1)t 
where  child_id is not null 

答案 2 :(得分:1)

基于示例数据? 这是一种简单的方法,也是一种更先进的方法。

请参阅下面的示例代码段:

declare @TestTable table (Cust_id int, ID int, [Date] date);

insert into @TestTable (Cust_id, ID, [Date]) values 
(75407014, 603, '2018-04-27'), 
(79807014, 603, '2018-04-30'), 
(75407016, 604, '2018-04-23'), 
(79807016, 604, '2018-04-30'), 
(75407018, 605, '2018-04-24'), 
(79807018, 605, '2018-04-30'), 
(75407020, 606, '2018-04-24'), 
(79807020, 606, '2018-04-30'), 
(75407014, 608, '2018-04-27');

--
-- Method 1: A simple self-join on ID and Date
-- This assumes that there are maximum 2 records per ID
--
select t1.Cust_id as Parent_id, t2.Cust_id as Child_id 
from @TestTable t1
join @TestTable t2 on (t2.ID = t1.ID and t2.[Date] > t1.[Date]);

--
-- Method 2: use a CTE with a row_number and self-join the CTE
--
;WITH CTE as (
  select 
    ID, 
    row_number() over (partition by ID order by [Date], Cust_id) as rn, 
    Cust_id 
  from @TestTable t
)
select t1.Cust_id as Parent_id, t2.Cust_id as Child_id
from CTE t1
join CTE t2 on (t1.ID = t2.ID and t1.rn = 1 and t2.rn > 1);

第二种方法允许每个父母有超过1个孩子。

答案 3 :(得分:0)

请试试这个

;WITH CTE(Cust_id,ID,[Date ])
AS
(
SELECT 75407014,603,'2018-04-27' UNION ALL 
SELECT 79807014,603,'2018-04-30' UNION ALL 
SELECT 75407016,604,'2018-04-23' UNION ALL 
SELECT 79807016,604,'2018-04-30' UNION ALL 
SELECT 75407018,605,'2018-04-24' UNION ALL 
SELECT 79807018,605,'2018-04-30' UNION ALL 
SELECT 75407020,606,'2018-04-24' UNION ALL 
SELECT 79807020,606,'2018-04-30' UNION ALL 
SELECT 75407014,608,'2018-04-27' 
)
,CTE_Final
AS
(
SELECT Cust_id
      ,ID
      ,[Date ]
      ,DENSE_RANK()OVER(ORDER BY ID) SEQ 
FROM CTE 
)
SELECT Parent_id
      ,Child_id 
FROM
    (
    SELECT SUBSTRING(Cust_id,0,CHARINDEX(',',Cust_id))  AS Parent_id,
       SUBSTRING(Cust_id,CHARINDEX(',',Cust_id)+1,LEN(Cust_id))AS Child_id 
     FROM
    (
    SELECT DISTINCT STUFF((SELECT DISTINCT  ', '+CAST(  Cust_id AS VARCHAR(10))
    FROM CTE_Final i WHERE i.SEQ=o.SEQ 
    FOR XML PATH ('')),1,1,'') AS  Cust_id
    FROM CTE_Final o
    )dt
)Dt2
WHERE  Dt2.Parent_id <> ''
ORDER BY Parent_id

结果

 Parent_id   Child_id
 --------------------
 75407014    79807014
 75407016    79807016
 75407018    79807018
 75407020    79807020

答案 4 :(得分:0)

           This query works if ID values repeat twice   
           SELECT * INTO TemP FROM
               (
                SELECT 75407014 Cust_id,    603 ID,   '2018-04-27'Date UNION
                SELECT 79807014 Cust_id,    603 ID,   '2018-04-30'Date UNION
                SELECT 75407016 Cust_id,    604 ID,   '2018-04-23'Date UNION
                SELECT 79807016 Cust_id,    604 ID,   '2018-04-30'Date UNION
                SELECT 75407018 Cust_id,    605 ID,   '2018-04-24'Date UNION
                SELECT 79807018 Cust_id,    605 ID,   '2018-04-30'Date UNION
                SELECT 75407020 Cust_id,    606 ID,   '2018-04-24'Date UNION
                SELECT 79807020 Cust_id,    606 ID,   '2018-04-30'Date UNION
                SELECT 75407014 Cust_id,    608 ID,   '2018-04-27'Date 
                )A

                SELECT *,ROW_number() OVER (PARTITION BY ID ORDER BY Date) RNO INTO #Tem
                FROM TEMP 

                SELECT K.Cust_id,L.cust_id
                FROM #Tem K
                INNER JOIN  #Tem L
                ON K.ID = L.ID AND K.RNO < L.RNO
相关问题