[英]Multiple Sub-Queries In A SQL Query
我正在創建一個示例查詢,該查詢會將行轉換為列,如下所示:
Person_Id Total Earned Leave Earned Leave Enjoyed Remaining Earned Leave Total Casual Leave Casual Leave Enjoyed Remaining Casual Leave
1001 20 10 10 20 4 16
因此,上面是使用以下查詢獲取並使用多個子查詢的輸出:
SELECT DISTINCT m.Person_Id, (SELECT k.Leave_Allocation FROM LeaveDetails k WHERE k.Leave_Name = 'Earn Leave'
AND k.Person_Id = 1001 AND k.[Year] = '2017') AS 'Total Earned Leave',
(SELECT o.Leave_Enjoy FROM LeaveDetails o WHERE o.Leave_Name = 'Earn Leave'
AND o.Person_Id = 1001 AND o.[Year] = '2017') AS 'Earned Leave Enjoyed',
(SELECT p.Leave_Remain FROM LeaveDetails p WHERE p.Leave_Name = 'Earn Leave'
AND p.Person_Id = 1001 AND p.[Year] = '2017') AS 'Remaining Earned Leave',
(SELECT k.Leave_Allocation FROM LeaveDetails k WHERE k.Leave_Name = 'Casual Leave'
AND k.Person_Id = 1001 AND k.[Year] = '2017') AS 'Total Casual Leave',
(SELECT o.Leave_Enjoy FROM LeaveDetails o WHERE o.Leave_Name = 'Casual Leave'
AND o.Person_Id = 1001 AND o.[Year] = '2017') AS 'Casual Leave Enjoyed',
(SELECT p.Leave_Remain FROM LeaveDetails p WHERE p.Leave_Name = 'Casual Leave'
AND p.Person_Id = 1001 AND p.[Year] = '2017') AS 'Remaining Casual Leave'
FROM LeaveDetails m WHERE m.Person_Id = 1001 AND m.[Year] = '2017'
我不確定在這里是否會有性能問題,因為會有很多數據,並且在爭論是否比Pivot或運行時表創建更好。 我只想確保這對於我要達到的目的是否是更好的選擇。 您可以使用SQL Server
, MySQL
或Oracle
分享您的想法以及示例,以獲取更好的性能問題-謝謝。
樣本表和數據:
CREATE TABLE [dbo].[LeaveDetails](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Person_Id] [nvarchar](20) NULL,
[Leave_Name] [nvarchar](40) NULL,
[Leave_Allocation] [float] NULL,
[Leave_Enjoy] [float] NULL,
[Leave_Remain] [float] NULL,
[Details] [nvarchar](100) NULL,
[Year] [nvarchar](10) NULL,
[Status] [bit] NULL
)
INSERT [dbo].[LeaveDetails] ([Id], [Person_Id], [Leave_Name], [Leave_Allocation], [Leave_Enjoy], [Leave_Remain], [Details], [Year], [Status]) VALUES (1, N'1001', N'Earn Leave', 20, 10, 10, NULL, N'2017', 1)
INSERT [dbo].[LeaveDetails] ([Id], [Person_Id], [Leave_Name], [Leave_Allocation], [Leave_Enjoy], [Leave_Remain], [Details], [Year], [Status]) VALUES (2, N'1001', N'Casual Leave', 20, 4, 16, NULL, N'2017', 1)
使用條件聚合:
SELECT m.Person_Id,
MAX(CASE WHEN m.Leave_Name = 'Earn Leave' THEN k.Leave_Allocation END) as [Total Earned Leave],
MAX(CASE WHEN m.Leave_Name = 'Earn Leave' THEN m.Leave_Enjoy END) as [Earned Leave Enjoyed],
MAX(CASE WHEN m.Leave_Name = 'Earn Leave' THEN m.Leave_Remain END) as [Remaining Earned Leave],
MAX(CASE WHEN m.Leave_Name = 'Casual Leave' THEN k.Leave_Allocation END) as [Total Casual Leave],
MAX(CASE WHEN m.Leave_Name = 'Casual Leave' THEN k.Leave_Remain END) as [Casual Leave Enjoyed],
MAX(CASE WHEN m.Leave_Name = 'Casual Leave' THEN k.Leave_Remain END) as [Remaining Casual Leave]
FROM LeaveDetails m
WHERE m.Person_Id = 1001 AND m.[Year] = '2017'
GROUP BY m.Person_ID;
注意:我不主張在列別名中使用特殊字符(例如空格)。 如果這樣做,請使用適當的轉義符(方括號)。 僅對字符串和日期常量使用單引號。
PIVOT可以工作,但看起來這只是您要透視到列輸出的單行,並且列名已明確知道。 如果是這樣的話,您可以將單列結果聯合起來:
SELECT 'Person_ID' as col_name, Person_Id as col_value FROM LeaveDetails WHERE Person_Id = 1001 AND [Year] = '2017'
UNION
SELECT 'Leave_Enjoy' as col_name, Leave_Enjoy as col_value FROM LeaveDetails WHERE Person_Id = 1001 AND [Year] = '2017'
UNION
...
編寫起來要簡單得多,閱讀起來也要干凈得多,並且運行起來應該快一些-每列仍然有一個表掃描。 該表是否在Person_ID和Year上建立索引?
如果速度是一個問題,則可以創建一行的臨時表:
SELECT * into #ld_temp FROM LeaveDetails WHERE Person_Id = 1001 AND [Year] = '2017'
然后從SELECT / UNION代碼的臨時表中選擇:
SELECT 'Person_ID' as col_name, Person_Id as col_value FROM #ld_temp
UNION
SELECT 'Leave_Enjoy' as col_name, Leave_Enjoy as col_value FROM #ld_temp
UNION
...
現在您只需要對大表進行一次掃描。
我希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.