SQL复杂转换

时间:2017-09-13 18:33:32

标签: sql sql-server tsql sql-server-2008-r2

我有吼叫,我想要的是任何由于地址变更而移动GP的人都应该有期间的开始日期和结束日期。但是,结束日期将是小于下一个开始日期的日期。请问我该如何撰写此查询?

DECLARE @Tab TABLE(Local_Patient_Identifier VARCHAR(70),    
    NHS_Number VARCHAR(70), GMP VARCHAR(70), Practice_Code_GP VARCHAR(70),  CDS_Date DATE)
INSERT INTO @Tab VALUES
('A111111111',  '8BFD000',  'G111111',  'N77777',   '2016-05-23'),
('A111111111',  '8BFD000',  'G222222',  'N77777',   '2016-06-13'),
('A111111111',  '8BFD000',  'G222222',  'N77777',   '2016-06-13'),
('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-02-09'),
('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-06'),
('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-15'),
('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-29'),
('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-05-10'),
('A111111112',  '8BFD002',  'G3333332', 'JJ44444',  '2015-05-21'),
('A111111112',  '8BFD002',  'G3333332', 'KK44445',  '2016-05-02'),
('A111111112',  '8BFD002',  'G3333332', 'WW44444',  '2017-02-13')
SELECT*FROM @Tab

预期输出 enter image description here

3 个答案:

答案 0 :(得分:1)

这是我如何去做它。我在工作时重新命名了这些列,因为我厌倦了输入长名字,但是我已经把它们弄错了,因为它更接近你的预期。我还使用英国日期格式(dd / mm / yyyy)转换输出日期以匹配您的输出

declare @tab table
(
    LPI varchar(70),    
    NHSNum varchar(70), 
    GMP varchar(70), 
    GP varchar(70),  
    CDSDate date
)
insert into @Tab 
values
    ('A111111111',  '8BFD000',  'G111111',  'N77777',   '2016-05-23'),
    ('A111111111',  '8BFD000',  'G222222',  'N77777',   '2016-06-13'),
    ('A111111111',  '8BFD000',  'G222222',  'N77777',   '2016-06-13'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-02-09'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-06'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-15'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-29'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-05-10'),
    ('A111111112',  '8BFD002',  'G3333332', 'JJ44444',  '2015-05-21'),
    ('A111111112',  '8BFD002',  'G3333332', 'KK44445',  '2016-05-02'),
    ('A111111112',  '8BFD002',  'G3333332', 'WW44444',  '2017-02-13')


;with src as
(
    select 
        RID = row_number() over (partition by LPI, NHSNum order by min(CDSDate)),    
        LPI, 
        NHSNum, 
        GMP, 
        GP,
        MinDate = min(CDSDate)
    from @tab
    group by     
        LPI, 
        NHSNum, 
        GMP, 
        GP
)
select 
    LocalPatientIdentifier = a.LPI,
    NHSNumber = a.NHSNum,
    GMP = a.GMP,
    PracticeCodeGP = a.GP,
    StartDate = convert(varchar(50), a.MinDate, 103),
    EndDate = convert(varchar(50), dateadd(day, -1, b.MinDate), 103)
from src a
left outer join src b
    on a.LPI = b.LPI
        and a.NHSNum = b.NHSNum
        and a.RID = b.RID - 1

答案 1 :(得分:1)

以下内容应该适用于SQL Server 2008R2 ...

import pandas as pd, numpy as np

d = [{'Cabin': 'F G13'},{'Cabin': 'A32 A45'},{'Cabin': 'F23 F36'},{'Cabin': 'B24'},{'Cabin': nan}]
df = pd.DataFrame(d)

def deck_list(row):
    if row['Cabin']!=row['Cabin']:
        cabinid = 'NONE'
    else:
        cabinsubstr = row['Cabin'].split(' ')
        for i in cabinsubstr:
            if i.find('F ') != -1:
                cabinid = i[0][0]
                break
            if i.find('F ') == 0:
                cabinid = i[1][0]
                break       
    return cabinid

df['Deck_ID'] = df.apply(deck_list, axis=1)

结果...

IF OBJECT_ID('tempdb..#Tab', 'U') IS NOT NULL 
DROP TABLE #Tab;

CREATE TABLE #Tab (
    Local_Patient_Identifier VARCHAR(70),    
    NHS_Number VARCHAR(70), 
    GMP VARCHAR(70), 
    Practice_Code_GP VARCHAR(70),  
    CDS_Date DATE
    );
INSERT #Tab (Local_Patient_Identifier, NHS_Number, GMP, Practice_Code_GP, CDS_Date) VALUES
    ('A111111111',  '8BFD000',  'G111111',  'N77777',   '2016-05-23'),
    ('A111111111',  '8BFD000',  'G222222',  'N77777',   '2016-06-13'),
    ('A111111111',  '8BFD000',  'G222222',  'N77777',   '2016-06-13'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-02-09'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-06'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-15'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-03-29'),
    ('A111111111',  '8BFD000',  'G3333333', 'ZZ44444',  '2017-05-10'),
    ('A111111112',  '8BFD002',  'G3333332', 'JJ44444',  '2015-05-21'),
    ('A111111112',  '8BFD002',  'G3333332', 'KK44445',  '2016-05-02'),
    ('A111111112',  '8BFD002',  'G3333332', 'WW44444',  '2017-02-13');

--  SELECT * FROM #Tab t

--======================================================================

IF OBJECT_ID('tempdb..#ChangeData', 'U') IS NOT NULL 
DROP TABLE #ChangeData;

WITH 
    cte_AddRN AS (
        SELECT 
            t.Local_Patient_Identifier,
            t.NHS_Number,
            t.GMP,
            t.Practice_Code_GP,
            t.CDS_Date,
            RN = ROW_NUMBER() OVER (PARTITION BY t.Local_Patient_Identifier, t.GMP, t.Practice_Code_GP ORDER BY t.CDS_Date)
        FROM 
            #Tab t
        )
SELECT 
    ar.Local_Patient_Identifier,
    ar.NHS_Number,
    ar.GMP,
    ar.Practice_Code_GP,
    ar.CDS_Date,
    RN = ROW_NUMBER() OVER (PARTITION BY ar.Local_Patient_Identifier ORDER BY ar.CDS_Date)
    INTO #ChangeData
FROM 
    cte_AddRN ar
WHERE 
    ar.RN = 1;

--  SELECT * FROM #ChangeData cd

SELECT
    cd1.Local_Patient_Identifier,
    cd1.NHS_Number,
    cd1.GMP,
    cd1.Practice_Code_GP,
    StartDate = cd1.CDS_Date,   
    EndDate = cd2.CDS_Date
FROM
    #ChangeData cd1
    LEFT JOIN #ChangeData cd2
        ON cd1.Local_Patient_Identifier = cd2.Local_Patient_Identifier
        AND cd1.RN = cd2.RN - 1;

答案 2 :(得分:1)

您可以使用row_Number来获得此结果:

;With Cte as (
    Select *,JoinKey = Row_Number() over(partition by Local_Patient_Identifier order by CDS_Date) from (
        Select *, RowN = Row_Number() over(partition by Local_patient_Identifier, GMP, Practice_Code_GP order by CDS_Date) 
            from #tab
        ) a
    where a.RowN = 1
)
Select c1.Local_Patient_Identifier,c1.NHS_Number, c1.GMP, c1.Practice_Code_GP, c1.CDS_Date as StartDate, 
    Dateadd(day, -1 , c2.CDS_Date) as EndDate from cte c1 left join cte c2
on c1.Local_Patient_Identifier = c2.Local_Patient_Identifier
and c1.JoinKey = c2.JoinKey - 1

输出如下:

+--------------------------+------------+----------+------------------+------------+------------+
| Local_Patient_Identifier | NHS_Number |   GMP    | Practice_Code_GP | StartDate  |  EndDate   |
+--------------------------+------------+----------+------------------+------------+------------+
| A111111111               | 8BFD000    | G111111  | N77777           | 2016-05-23 | 2016-06-12 |
| A111111111               | 8BFD000    | G222222  | N77777           | 2016-06-13 | 2017-02-08 |
| A111111111               | 8BFD000    | G3333333 | ZZ44444          | 2017-02-09 | NULL       |
| A111111112               | 8BFD002    | G3333332 | JJ44444          | 2015-05-21 | 2016-05-01 |
| A111111112               | 8BFD002    | G3333332 | KK44445          | 2016-05-02 | 2017-02-12 |
| A111111112               | 8BFD002    | G3333332 | WW44444          | 2017-02-13 | NULL       |
+--------------------------+------------+----------+------------------+------------+------------+

如果您使用的是SQL Server> = 2012

,则可以使用窗口函数线索