我正在尝试写一些东西来自动清理一些旅行数据。将这些视为航班:
航班:
ID DocType Name Travel Date Fare Paid
1 INV Mrs G 13/03/2017 37.6
2 INV Mrs G 13/03/2017 200
3 INV Mr H 14/03/2017 60
4 INV Mr H 15/03/2017 126
5 CRN Mr H 15/03/2017 126
6 INV Mr H 20/03/2017 126
7 INV Mrs S 29/03/2017 110
8 INV Mr J 26/03/2017 54
9 INV Mr R 13/03/2017 200
10 INV Miss C 27/03/2017 78.98
有时人们会购买航班,然后获得退款。这显示为数据中的两个相同条目,但退款是DocType' CRN'。我需要能够从数据集中提取预订和退款行。
我可以为CRN标记的行执行此操作。但是,如何拉出CRN行上方的行?相关INV行的ID将始终具有直接且顺序地低于CRN行的ID。
我已经管理了
INSERT INTO TRAVEL.REFUNDS (ID, DocType, Name, [Travel Date], [Fare Paid])
SELECT ID, DocType, Name, [Travel Date], [Fare Paid]
FROM TRAVEL.FLIGHTS
WHERE [DocType] = 'CRN';
GO
提前谢谢
答案 0 :(得分:0)
这是SELECT
目的,不确定您是想要它还是INSERT
或DELETE
,但希望它很容易对那些人加以改变,再加上它们修改前要好好检查一下,对吧?
我正在做的是,我使用LAG / LEAD添加一个新列,这主要是其他一些行列,虽然向上或向下移动了一行。有了这个,您将每行包含决定如何处理它的所有内容,这将在针对较低查询结果的较高查询中完成。
-- Making an MCVE, first time I know its name though.
DECLARE @Flights TABLE (ID int, DocType char(3))
INSERT INTO @Flights VALUES
( 1, 'INV')
, ( 2, 'INV')
, ( 3, 'INV') -- Should not show up.
, ( 4, 'CRN') -- Should not show up.
, ( 5, 'INV')
, ( 6, 'INV')
, ( 7, 'INV')
, ( 8, 'INV')
, ( 9, 'INV')
, (10, 'INV') -- Should not show up.
, (11, 'CRN') -- Should not show up.
-- Querying via LEAD(), with 1 level nesting (or subquerying, I dunno which is which).
SELECT *
FROM (
SELECT ID
, DocType AS DocTypeThis
, LEAD(DocType) OVER(ORDER BY ID ASC) AS DocTypeOther -- Seems like the choice of ASC/DESC reverses LAG/LEAD behaviours into each other, although not sure.
FROM @Flights
) AS T
WHERE (DocTypeOther IS NULL AND DocTypeThis = 'INV') -- Special treatment for last row (for other implementations, might be first row).
OR DocTypeThis = DocTypeOther -- This is the core of filtering, this fails only when the row is a 'CRN', or is superceded directly by a 'CRN'.
ORDER BY ID ASC
答案 1 :(得分:0)
使用exists()
:
select *
from t
where DocType = 'CRN'
or exists (
select 1
from t i
where i.DocType='CRN'
and i.id-1 = t.id
)
或left join
select t.*
from t
left join t i
on i.id-1 = t.id
where t.DocType = 'CRN'
or i.DocType = 'CRN'
rextester演示:rextester.com/MSGGX10058
返回:
+----+---------+--------+------------+----------+
| ID | DocType | Name | TravelDate | FarePaid |
+----+---------+--------+------------+----------+
| 4 | INV | Mr H | 15.03.2017 | 126.00 |
| 5 | CRN | Mr H | 15.03.2017 | 126.00 |
+----+---------+--------+------------+----------+
使用not exists()
作为相反的结果集:
select *
from t
where DocType = 'INV'
and not exists (
select 1
from t i
where i.DocType='CRN'
and i.id-1 = t.id
)
返回:
+----+---------+--------+------------+----------+
| ID | DocType | Name | TravelDate | FarePaid |
+----+---------+--------+------------+----------+
| 1 | INV | Mrs G | 13.03.2017 | 37.60 |
| 2 | INV | Mrs G | 13.03.2017 | 200.00 |
| 3 | INV | Mr H | 14.03.2017 | 60.00 |
| 6 | INV | Mr H | 20.03.2017 | 126.00 |
| 7 | INV | Mrs S | 29.03.2017 | 110.00 |
| 8 | INV | Mr J | 26.03.2017 | 54.00 |
| 9 | INV | Mr R | 13.03.2017 | 200.00 |
| 10 | INV | Miss C | 27.03.2017 | 78.98 |
+----+---------+--------+------------+----------+