从sql走向linq的我撞死在起点上


【本文纯个人理解,错误轻喷,非常希望能有大神指点】

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 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 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))
上面第二行,我图灰了的,是我在网上找到的right join。之所以图黑,是因为我觉得它不对,它其实也是左连接,只是把左右两张表顺序换了而已。我也未曾找到实现right join的Linq语句。而随着我的不断寻找,我越来越多的接触到一直说法,也就是,Linq与sql无关性。当然,意思并不是说linq与sql是没有关系的,相反,它们的关系非常大,但是,如果我们想linq的时候总是被sql的想法左右,会导致一些大家都不愿意看到的结果,比如有些本来很简单的工作我们把它弄得复杂甚至无法解决。因为我们面对的不再是【表】而是【对像】。 所以,我抛开了上面那种寻找左右联接与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一杦,现在,知耻而后勇,进行再学习。后面我们继续把我的学习笔记送上来~~