簡體   English   中英

SQL查詢中的多個子查詢

[英]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 ServerMySQLOracle分享您的想法以及示例,以獲取更好的性能問題-謝謝。

樣本表和數據:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM