[英]T-SQL Query Column based on filtered condition
我可以用 Python(或任何其他語言)很容易地做到這一點,但我想看看這是否可以用純 T-sql
我有兩個表:
表 A 的每一行都有一堆通用數據和時間戳
+------+------+------+-----------+
| Col1 | Col2 | Col3 | Timestamp |
+------+------+------+-----------+
| A | B | C | 17:00 |
| D | E | F | 18:00 |
| G | H | I | 23:00 |
+------+------+------+-----------+
表 B 被視為元數據
+-------+-----------+
| RunNo | Timestamp |
+-------+-----------+
| 1 | 16:50 |
| 2 | 17:30 |
| 3 | 18:00 |
| 4 | 19:00 |
+-------+-----------+
所以一般數據被引用到“RunNo”。 表 B 中的時間戳正好是在數據庫中創建“運行”的時間。 您可以通過比較時間戳將常規數據與其正確的運行編號進行匹配。 例如,表 A 中第一行的時間戳為 17:00,大於 16:50 且小於 17:30,因此顯然該行屬於 RunNo 1。如何執行此查詢,以便生成的表是
+------+------+------+-----------+-------+
| Col1 | Col2 | Col3 | Timestamp | RunNo |
+------+------+------+-----------+-------+
| A | B | C | 17:00 | 1 |
| D | E | F | 18:00 | 2 |
| G | H | I | 23:00 | 4 |
+------+------+------+-----------+-------+
我雖然在這里使用 CASE 可能會有所幫助,但我不知道如何把它放在一起
SELECT a.*,
CASE WHEN a.TIMESTAMP < b.TIMESAMP AND a.TIMESTAMP > b.TIMSTAMP then b.RunNo END AS RunNo
FROM A as a, B as b
任何幫助將不勝感激。
CASE
允許您根據條件返回不同的值(即列或表達式)。 這不是你這里的什么。 您想要連接表並根據條件過濾匹配的行。
我已經用ts
替換了名稱Timestamp
,因為即使逃脫了,我在SQL Fiddle上也遇到了困難。 它是一個保留關鍵字。
SELECT A.Col1, A.Col2, A.Col3, A.ts, MAX(B.RunNo) AS RunNo
FROM
A
INNER JOIN B
ON A.ts > B.ts
GROUP BY A.Col1, A.Col2, A.Col3, A.ts
使用A.ts > B.ts
這會為第二個條目返回RunNo
2。 如果A.ts >= B.ts
這將返回第二個條目的RunNo
3。
with TableA as (
Select [Col1] = 'A',[Col2] = 'B',[Col3] = 'C',[Timestamp] = '17:00'
Union all Select [Col1] = 'D',[Col2] = 'E',[Col3] = 'F',[Timestamp] = '18:00'
Union all Select [Col1] = 'G',[Col2] = 'H',[Col3] = 'I',[Timestamp] = '23:00'
)
, TableB as (
Select [RunNo] = '1',[Timestamp] = '16:50'
Union all Select [RunNo] = '2',[Timestamp] = '17:30'
Union all Select [RunNo] = '3',[Timestamp] = '18:00'
Union all Select [RunNo] = '4',[Timestamp] = '19:00'
)
, TableBWithRowNumber as (
select b.RunNo, ROW_NUMBER() over (order by b.timestamp asc) as number, cast(b.Timestamp as time) as timestamp
from TableB b
)
, TableBWithNextRun as (
select b1.RunNo, startTime = b1.timestamp , endTime = b2.timestamp
from TableBWithRowNumber b1
left join TableBWithRowNumber b2 on b1.number + 1= b2.number
)
select *
from TableA a
inner join TableBWithNextRun B
on a.Timestamp >= b.startTime and (a.Timestamp < b.endTime or b.endTime is null)
這會將您的時間戳轉換為time
。 我不確定你的內部數據類型是什么。
這輸出以下
Col1 Col2 Col3 Timestamp RunNo startTime endTime
A B C 17:00 1 16:50:00.0000000 17:30:00.0000000
D E F 18:00 3 18:00:00.0000000 19:00:00.0000000
G H I 23:00 4 19:00:00.0000000 NULL
您可以使用滯后函數獲取列的先驗值,然后加入。
WITH Runs AS
(
SELECT
RunNo,
COALESCE(LAG(TIMESTAMP),'00:00')) AS START_TS,
TIMESTAMP AS END_TS
FROM TableB
ORDER BY RunNo ASC
)
SELECT B.RunNo, A.*
FROM TableA A
JOIN Runs B ON A.Timestamp >= B.Start_TS AND A.Timestamp < B.End_Ts
這應該比更大數據集上的任何 group by 解決方案都快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.