我遇到了一個問題,我誤解了左連接是什么,而且我真的不知道如何表達這個問題。我在下面有一個 MVCE
declare @matchableproperties table
(
pname varchar(100)
)
declare @users table
(
userid varchar(100),
pname varchar(100),
pvalue varchar(100)
)
insert into @matchableproperties values ('city')
insert into @matchableproperties values ('status')
insert into @matchableproperties values ('position')
insert into @users values (1, 'city', 'Wichita')
insert into @users values (1, 'status', 'Active')
insert into @users values (1, 'position', 'Captain')
insert into @users values (2, 'city', 'Wichita')
insert into @users values (2, 'status', 'Active')
select u.*, mp.* from @matchableproperties mp
left join @users u on mp.pname = u.pname
order by userid, mp.pname
回傳
| u.userid | u.pname | 上正值 | mp.pname |
|---|---|---|---|
| 1 | 城市 | 威奇托 | 城市 |
| 1 | 位置 | 隊長 | 位置 |
| 1 | 地位 | 積極的 | 地位 |
| 2 | 城市 | 威奇托 | 城市 |
| 2 | 地位 | 積極的 | 地位 |
我的問題在于我想要實作的目標。我想知道,對于每個用戶 ID,哪些 pname 存在,哪些 pname 不存在。就像,對于用戶 ID 2,“位置”pname 不存在,所以我想在下面有一個額外的行來顯示用戶 ID 2 與所有指定的屬性都不匹配。
| u.userid | u.pname | 上正值 | mp.pname |
|---|---|---|---|
| 2 | 空值 | 空值 | 位置 |
考慮到這一點后,我意識到我想對用戶表的各個磁區進行左連接——本質上我想要的結果
select u.*, mp.* from @matchableproperties mp
left join (select * from @users where userid = 1) u on mp.pname = u.pname
union all
select u.*, mp.* from @matchableproperties mp
left join (select * from @users where userid = 2) u on mp.pname = u.pname
上面的查詢給了我想要的結果(上面的兩個表,總共六行),但是由于我不知道有多少用戶將不在 users 表中,我顯然無法對其進行硬編碼。是否有一些神奇的“partition by”或“group by”語法我可以在左連接上使用來從兩個表上的單個左連接陳述句中獲得我想要的東西?
uj5u.com熱心網友回復:
您需要對每個可能的屬性和用戶組合進行預測。那是一個CROSS JOIN。一旦你有了這個投影,你就可以 LEFT JOIN 回到 users 表來查看實際匹配的內容:
SELECT u0.userid, mp.pname, u.pvalue
FROM (
SELECT DISTINCT pname FROM @matchableproperties
) mp
CROSS JOIN (
SELECT DISTINCT userid FROM @users
) u0
LEFT JOIN @users u on u.userid = u0.userid and u.pname = mp.pname
在這里看到它的作業:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=533c75a50d6627fdc831b77c5dea47d3
這種對交叉連接的需求往往會在資料庫服務器上使用大量記憶體和資源,這是最好避免使用此類 EAV 模式的幾個原因之一。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/463334.html
