SQL如何选择行正上方的行的内容,并将两者移动到新表中
我正在尝试写一些东西来自动清理一些旅行数据。将这些视为航班: 航班:SQL如何选择行正上方的行的内容,并将两者移动到新表中,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在尝试写一些东西来自动清理一些旅行数据。将这些视为航班: 航班: 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
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
提前谢谢你这是为了
选择
的目的,不确定你是想要它还是插入
或删除
,但希望它可以很容易地重新编写,而且在修改之前检查一下也很好,对吗
我正在做的是,我正在使用/添加一个新列,它主要是其他行列的副本,尽管它向上或向下移动了一行。这样,每一行都将包含决定如何处理它所需的所有内容,这将在针对较低查询结果的较高查询中完成
-- 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
这是为了
SELECT
的目的,不确定您是否需要它,或者INSERT
或者DELETE
,但是希望它可以很容易地重新编写,而且在修改之前检查一下也很好,对吗
我正在做的是,我正在使用/添加一个新列,它主要是其他行列的副本,尽管它向上或向下移动了一行。这样,每一行都将包含决定如何处理它所需的所有内容,这将在针对较低查询结果的较高查询中完成
-- 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
使用exists()
:
或左连接
select t.*
from t
left join t i
on i.id-1 = t.id
where t.DocType = 'CRN'
or i.DocType = 'CRN'
rextester演示:
返回:
+----+---------+--------+------------+----------+
| ID | DocType | Name | TravelDate | FarePaid |
+----+---------+--------+------------+----------+
| 4 | INV | Mr H | 15.03.2017 | 126.00 |
| 5 | CRN | Mr H | 15.03.2017 | 126.00 |
+----+---------+--------+------------+----------+
+----+---------+--------+------------+----------+
| 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 |
+----+---------+--------+------------+----------+
对相反的结果集使用
notexists()
:
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 |
+----+---------+--------+------------+----------+
| 4 | INV | Mr H | 15.03.2017 | 126.00 |
| 5 | CRN | Mr H | 15.03.2017 | 126.00 |
+----+---------+--------+------------+----------+
+----+---------+--------+------------+----------+
| 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 |
+----+---------+--------+------------+----------+
使用exists()
:
或左连接
select t.*
from t
left join t i
on i.id-1 = t.id
where t.DocType = 'CRN'
or i.DocType = 'CRN'
rextester演示:
返回:
+----+---------+--------+------------+----------+
| ID | DocType | Name | TravelDate | FarePaid |
+----+---------+--------+------------+----------+
| 4 | INV | Mr H | 15.03.2017 | 126.00 |
| 5 | CRN | Mr H | 15.03.2017 | 126.00 |
+----+---------+--------+------------+----------+
+----+---------+--------+------------+----------+
| 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 |
+----+---------+--------+------------+----------+
对相反的结果集使用
notexists()
:
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 |
+----+---------+--------+------------+----------+
| 4 | INV | Mr H | 15.03.2017 | 126.00 |
| 5 | CRN | Mr H | 15.03.2017 | 126.00 |
+----+---------+--------+------------+----------+
+----+---------+--------+------------+----------+
| 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 |
+----+---------+--------+------------+----------+
每个CRN行是否总是在其正上方有其相关的INV?如果情况并非总是如此,则“拉出CRN行正上方的行”将无济于事。如果它总是出现在正上方。。。是否因此而产生了订单条款?如果是的话,你点什么?谢谢你的回复。作为回应,我把数据集弄得更清楚了。相关INV始终位于CRN行的正上方,因为这是提供数据的方式。我立即上传到SQL中,并分配一个ID(主键),它现在位于数据集中。我曾考虑过order by,但无法解决如何在INSERT INTO指令中进行通信。鉴于RDBMS中的行表示无序集,请定义“以上”。请看:相关的INV有一个ID,它是顺序的,并且直接地,在CRN行ID之前(‘上面’)(我在文章中已经清楚地说明了这一点)。欢迎您不要提供任何东西。谢谢您的光临。每个CRN行都会在其正上方有其相关的INV吗?如果情况并非总是如此,则“拉出CRN行正上方的行”将无济于事。如果它总是出现在正上方。。。是否因此而产生了订单条款?如果是的话,你点什么?谢谢你的回复。作为回应,我把数据集弄得更清楚了。相关INV始终位于CRN行的正上方,因为这是提供数据的方式。我立即上传到SQL中,并分配一个ID(主键),它现在位于数据集中。我曾考虑过order by,但无法解决如何在INSERT INTO指令中进行通信。鉴于RDBMS中的行表示无序集,请定义“以上”。请看:相关的INV有一个ID,它是顺序的,并且直接地,在CRN行ID之前(‘上面’)(我在文章中已经清楚地说明了这一点)。欢迎您不要提供任何东西。谢谢你的来访。非常感谢你抽出时间。我已经测试过了,效果很好。@JER很乐意帮忙!非常感谢您抽出时间。我已经测试过了,效果很好。@JER很乐意帮忙!我真的很感谢你的解释。我还没能为我的桌子翻译这个,但我会继续尝试,因为我从来没有使用过LAG,我想掌握这个窍门it@JER,不客气,仅供参考,代码和文本中有一些错误,我更正了这些错误并重新措辞,这些都在编辑历史记录的第4项下。我非常感谢您的解释。我还没能为我的桌子翻译这个,但我会继续尝试,因为我从来没有使用过LAG,我想掌握这个窍门it@JER,不客气,仅供参考,代码和文本中有一些错误,我更正了这些错误并重新措辞,这些都在编辑历史记录中的第4项下。