【本文純個人理解,錯誤輕噴,非常希望能有大神指點】
A left (outer) join B on A.bid=B.id
上面這句話叫做左連接,原因是left(左)join(加入,連入)被譯為左連接,所以,這是關於語法中關鍵字的翻譯,而非連接原理,造成不能以為是從第一張表的左邊連接。相反,它是從A表的右邊開始連接的。原因很簡單,比如一個普通的查詢語句:select t.id TID from table1 t。后面的那個t是對table1的標記,再看TID它也是對t.id的標記,它們的功能是什么我們暫且不說,起碼我們知道了sql的語法習慣是將附加的參數或者說明后置。這樣我就再看上面的左連語句,就知道了left和join屁關系沒有。語句的划分應該是:
select A.*
from
A left
join B
on A.bid=B.id。outer沒寫,是因為所有的left join都是left outer join,right join類推!回到我們剛剛的那個語法,紅色的部分代表了整個語句的操作及限定關鍵字,而left則是A的后置附加信息,它的意思是說,A是放在左邊的,同樣,你若把left換成Right就成了A放在右邊,而如果后面加了Outer了呢,outer和join對是一對,他倆與inner join相對應,這下就好理解了,因為inner join將兩張表里面所有的為空的記錄都棄掉,所以,不需要哪個是左哪個是右,所以,A表后面的left或者right就被省略了,直接是A inner join B on。話說回來了,為什么要分左邊呢?很簡單,我們畫表喜歡從左往右,左邊定下了,再畫右邊,也就是,先把左邊的表查出來,再把右邊的取出來往上面拼,能拼多少拼多少。
【linq中的左右內連接】
linq的lambda
|
生成的sql
|
var queryLeft =
from t in con.TRANSSECTION_BASEPRICE
join u in con.SYS_STAFF on t.INPUT_MAN equals u.CODEUSER
into TranNew
from
tr
in TranNew.DefaultIfEmpty()
select new
{
t.DEST_PLACE,
t.IF_VALID,
t.INFO_ID,
t.INPUT_TIME,
INPUTMAN =tr==null?t.INPUT_MAN: tr.USERNAME
};
|
SELECT
1 AS "C1",
"Extent1"."DEST_PLACE" AS "DEST_PLACE",
"Extent1"."IF_VALID" AS "IF_VALID",
"Extent1"."INFO_ID" AS "INFO_ID",
"Extent1"."INPUT_TIME" AS "INPUT_TIME",
CASE WHEN ("Extent2"."ID" IS NULL) THEN "Extent1"."INPUT_MAN" ELSE "Extent2"."USERNAME" END AS "C2"
FROM "JSXW"."TRANSSECTION_BASEPRICE" "Extent1"
LEFT OUTER JOIN "JSXW"."SYS_STAFF" "Extent2" ON ("Extent1"."INPUT_MAN" = "Extent2"."CODEUSER") OR (("Extent1"."INPUT_MAN" IS NULL) AND ("Extent2"."CODEUSER" IS NULL))
|
var queryRight = from u in con.SYS_STAFF
join t in con.TRANSSECTION_BASEPRICE on u.CODEUSER equals t.INPUT_MAN
into unew
from un in unew.DefaultIfEmpty()
select new
{
un.DEST_PLACE,
un.IF_VALID,
un.INFO_ID,
un.INPUT_TIME,
INPUTMAN = u.USERNAME
};
|
SELECT
1 AS "C1",
"Extent2"."DEST_PLACE" AS "DEST_PLACE",
"Extent2"."IF_VALID" AS "IF_VALID",
"Extent2"."INFO_ID" AS "INFO_ID",
"Extent2"."INPUT_TIME" AS "INPUT_TIME",
"Extent1"."USERNAME" AS "USERNAME"
FROM "JSXW"."SYS_STAFF" "Extent1"
LEFT OUTER JOIN "JSXW"."TRANSSECTION_BASEPRICE" "Extent2" ON ("Extent1"."CODEUSER" = "Extent2"."INPUT_MAN") OR (("Extent1"."CODEUSER" IS NULL) AND ("Extent2"."INPUT_MAN" IS NULL))
|
var queryInner = from t in con.TRANSSECTION_BASEPRICE
join u in con.SYS_STAFF on t.INPUT_MAN equals u.CODEUSER
select new
{
t.DEST_PLACE,
t.IF_VALID,
t.INFO_ID,
t.INPUT_TIME,
INPUTMAN = u.USERNAME
};
|
SELECT
1 AS "C1",
"Extent1"."DEST_PLACE" AS "DEST_PLACE",
"Extent1"."IF_VALID" AS "IF_VALID",
"Extent1"."INFO_ID" AS "INFO_ID",
"Extent1"."INPUT_TIME" AS "INPUT_TIME",
"Extent2"."USERNAME" AS "USERNAME"
FROM "JSXW"."TRANSSECTION_BASEPRICE" "Extent1"
INNER JOIN "JSXW"."SYS_STAFF" "Extent2" ON ("Extent1"."INPUT_MAN" = "Extent2"."CODEUSER") OR (("Extent1"."INPUT_MAN" IS NULL) AND ("Extent2"."CODEUSER" IS NULL))
|
所以,我拋開了上面那種尋找左右聯接與linq的思路,把自己想成一個不會sql的新人,去學習linq。而就在我學習linq的時候,發現linq中有許多sql里面根本沒有的東西,而這些東西,通常是我們可以繞開sql中的復雜聯接可以直接得到的。
而且我發現,linq中的join與sql中的join完全不是一個東西,或者說,它們根本沒有血緣關系,有點兒像c與c++的感覺。
這樣,我們就必須有一種新的思路,要找尋這條新的思路,我們要先看看我們之前為什么要尋找linq與sql的關系。
{查詢數據的需求}--->
{本來用sql的時候我們會寫成的sql語句}--->
{與sql語句相匹配的linq}
看吧,我們明知道sql轉linq沒有教程,linq轉sql微軟也沒有明確給出算法,我們卻還要這般折磨自己,何苦呢~~
那么我們就收回那顆自以為自己很牛逼的心,把我們的做法換一下:
{查詢數據的需求}--->
{解決需求的linq}
這種情況下,我們只會遇見兩人種問題:一、linq完成不了我們的需求;二、效率問題。我們先來一個個看。第一個,我覺得問題不大,畢竟是一種語言,語言都是符合語言的規格的,沒有它完不成的需求,只有它顧及不上的第二人問題。我們來看第二個問題,就是效率問題,這確實是一個大問題 ,因為,如果你寫linq寫得熱血朝天,那么你完全可以認為,你的linq效率極低,我看見過一條linq語句,里面有幾十個方法。linq也像sql一樣,是一種需要構造的語言,所以,在寫之前,我們必須要對linq進行深入的理解與學習,就像當初學習sql一樣,看一條sql完全可以執行它大概的執行復雜度。好了,我們的問題出來了,就是學習linq!
linq之前我也有學習過,也有用過,但是,當時太年輕了,小菜b一杦,現在,知恥而后勇,進行再學習。后面我們繼續把我的學習筆記送上來~~