• 从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一杦,现在,知耻而后勇,进行再学习。后面我们继续把我的学习笔记送上来~~
  • 相关阅读:
    剑指Offer(Java版)第四十六题:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。
    剑指Offer(Java版)第四十五题:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
    剑指Offer(Java版)第四十四题:输入一棵二叉树,判断该二叉树是否是平衡二叉树。
    剑指Offer(Java版)第四十三题:输入一棵二叉树,求该树的深度。 从根结点到叶结点依次经过的结点 (含根、叶结点)形成树的一条路径, 最长路径的长度为树的深度。
    剑指Offer(Java版)第四十二题:统计一个数字在排序数组中出现的次数。
    剑指Offer(Java版)第四十一题:输入两个链表,找出它们的第一个公共结点。
    剑指Offer(Java版)第四十题:在数组中的两个数字,如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。 并将P对1000000007取模的结果输出。 即输出P%1000000007
    剑指Offer(Java版)第三十九题:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符, 并返回它的位置, 如果没有则返回 -1(需要区分大小写).
    剑指Offer(Java版)第三十八题:把只包含质因子2、3和5的数称作丑数(Ugly Number)。 例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。 求按从小到大的顺序的第N个丑数。
    【微信支付】退款
  • 原文地址:https://www.cnblogs.com/ensleep/p/3628642.html
Copyright © 2020-2023  润新知