簡體   English   中英

如何將多個子選擇的SQL壓縮為更合理的東西?

[英]How do I condense this SQL of multiple sub-selects into something more sane?

以下查詢根據需要返回單行。 “合同”表有6個字段,每個字段中都有不同的用戶名,我想從一個單獨的“用戶”表中檢索其名字/姓氏。 這可以正常工作,但還有其他更簡潔的方法嗎? 我認為解決方案一定是使用GROUP BY Contracts.id使其保持一行的方法,但是我似乎找不到比這一系列子選擇更好的方法。

救命!

SELECT contracts.field1, contracts.field2, 
(SELECT first_name FROM users WHERE username = service_provider_1),
(SELECT last_name FROM users WHERE username = service_provider_1),
(SELECT first_name FROM users WHERE username = service_provider_2),
(SELECT last_name FROM users WHERE username = service_provider_2),
(SELECT first_name FROM users WHERE username = service_org_business_contact),
(SELECT last_name FROM users WHERE username = service_org_business_contact),
(SELECT first_name FROM users WHERE username = client_service_contact_1),
(SELECT last_name FROM users WHERE username = client_service_contact_1),
(SELECT first_name FROM users WHERE username = client_service_contact_2),
(SELECT last_name FROM users WHERE username = client_service_contact_2),
(SELECT first_name FROM users WHERE username = client_business_contact),
(SELECT last_name FROM users WHERE username = client_business_contact)
FROM contracts
WHERE id = ?

如果我可以從一個子選擇中同時獲得名字/姓氏,那並不會太糟糕……因此,即使采用了糟糕的子選擇解決方案,我的冗長程度也應該是我認為的兩倍...

編輯:我現在知道了。 能夠多次連接到同一表的答案是為表使用別名。 謝謝大家! 新代碼是:

SELECT contracts.field1, contracts.field2, 
sp1.first_name, sp1.last_name, 
sp2.first_name, sp2.last_name, 
sobc.first_name, sobc.last_name, 
csc1.first_name, csc1.last_name, 
csc2.first_name, csc2.last_name, 
cbc.first_name, cbc.last_name
FROM contracts
JOIN users AS sp1 ON service_provider_1 = sp1.username
JOIN users AS sp2 ON service_provider_2 = sp2.username
JOIN users AS sobc ON service_org_business_contact = sobc.username
JOIN users AS csc1 ON client_service_contact_1 = csc1.username
JOIN users AS csc2 ON client_service_contact_2 = csc2.username
JOIN users AS cbc ON client_business_contact = cbc.username
WHERE contracts.id = ?

可悲的是,使用聯接幾乎與使用子選擇一樣冗長,但是我認為它可能更快?

為什么不加入6次用戶表?

SELECT contracts.field1, contracts.field2, 
sp1.first_name,
sp1.last_name 
sp2.first_name,
sp2.last_name,
/* etc, etc */
FROM
contracts
INNER JOIN
users sp1
ON
contracts.id = sp1.id
AND sp1.username = service_provider_1
INNER JOIN 
users sp2
ON contracts.id = sp2.id
AND sp2.username = service_provider_2
INNER JOIN 
users sobc
ON contracts.id = sobc.id
AND sobc.username = service_org_business_contact
INNER JOIN
/* etc, etc */
WHERE contracts.id = @myid

您是否還想為每個用戶名組合first_namelast_name 你可以這樣做

RTRIM(sp1.first_name) + ' ' + RTRIM(sp1.last_name) as sp1_name

在您的SELECT子句中。 如果數據類型為(N)CHAR,則RTRIM是必需的;如果數據類型為(N)VARCHAR,則不需要RTRIM

編輯:對此答案的評論中所述,id上的JOIN可能不是必需的,在這種情況下,它變為

SELECT 
contracts.field1, 
contracts.field2, 
sp1.first_name,
sp1.last_name 
sp2.first_name,
sp2.last_name,
/* etc, etc */
FROM
contracts
INNER JOIN
users sp1
ON
sp1.username = service_provider_1
INNER JOIN 
users sp2
ON
sp2.username = service_provider_2
INNER JOIN 
users sobc
ON 
sobc.username = service_org_business_contact
INNER JOIN
/* etc, etc */
WHERE contracts.id = @myid

我的布局可能會使它看起來更長! 如果可能有一個合同記錄,而該記錄沒有在users表中的其中一個字段具有first_namelast_name ,則可能需要使用LEFT OUTER JOINS。

select 
 c.field1,c.field2
,SP1.first_name ,SP1.last_name
,SP2.first_name ,SP2.last_name
,SOBC.first_name,SOBC.last_name
,CSC1.first_name,CSC1.last_name
,CSC2.first_name,CSC2.last_name
,CBC.first_name ,CBC.last_name
from contracts C
left join users as SP1  on SP1.Username  = C.service_provider_1 
left join users as SP2  on SP2.Username  = C.service_provider_2 
left join users as SOBC on SOBC.Username = C.service_org_business_contact 
left join users as CSC1 on SP1.Username  = C.client_service_contact_1 
left join users as CSC2 on SP1.Username  = C.client_service_contact_2 
left join users as CBC  on CBC.Username  = C.client_business_contact 

where c.ID = ?

我忍不住認為將名稱與名稱類型的列一起推到單獨的表中可能是個好主意。

編輯:或者在合同和用戶之間放置另一個聯接表,以正確進行多對多聯接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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