【问题标题】:Left join two datatables with certain parameters左连接具有某些参数的两个数据表
【发布时间】:2020-05-27 10:11:45
【问题描述】:

我有两个数据表 t1t2。将它们导入 SQL,使用 SQL 命令LEFT JOIN 进行测试,它正在工作。但是,由于数据量不是很大,我想知道是否可以直接对数据表执行相同的操作而不将它们导出到 SQL?

这里我在 SQL LFI = t1LSE = t2 中有两个表。

数据库中的表LFI

NRO   SNAME  NAMEA   NAMEB   IADDRESS  POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   BID
123   Fiat   Punto   500     J5        K4      O3      P4        O2         JT        S1
133   Opel   Meriva  FTG     J5        K4      O3      P4        O2         JO        T3
153   MB     E200    C25     JN        KI      OP      PY        OR         JD        Y5
183   BMW    E64     SE0     JR        KE      OT      PG        OL         J8        U9 
103   Audi   S6      700     JP        KU      OU      PN        OH         J6        I11

数据库中的表LSE

NRO   SNAME  NAMEA   NAMEB   IADDRESS  POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   BID
423   Fiat   Punto   500     J5        K4      O3      P4        O2         JT        S1
463   BMW    E64     SE0     JR        KE      OT      PG        OL         J8        U9
483   KIA    E89     S78     J7        K7      O9      P6        O5         J4        U6

以下代码能够完成预期的工作:

SELECT *
FROM LFI
LEFT JOIN LSE 
ON CAST(LFI.SNAME AS VARCHAR(50)) = CAST(LSE.SNAME AS VARCHAR(50));

如何直接对数据表执行相同的操作,以便连接的结果将通过LEFT JOIN 转到temporary 数据表?


当前代码:

                var results = from table1 in t1.AsEnumerable()
                              join table2 in t2.AsEnumerable() 
                              on (string)table1["SNAME"] equals (string)table2["SNAME"]
                              //into temp
                              //from row in temp.DefaultIfEmpty()
                              select new
                              {
                                  NRO = (string)table1["NRO"],
                                  SNAME = (string)table1["SNAME"],
                                  NAMEA = (string)table1["NAMEA"],
                                  NAMEB = (string)table1["NAMEB"],
                                  ADDRESS = (string)table1["ADDRESS"],
                                  POSTA = (string)table1["POSTA"],
                                  POSTN = (string)table1["POSTN"],
                                  POSTITP = (string)table1["POSTITP"],
                                  COMPANYN = (string)table1["COMPANYN"],
                                  COUNTRY = (string)table1["COUNTRY"],
                                  BID = (string)table1["BID"]
                              };

                foreach (var item in results)
                {
                    Console.WriteLine(String.Format("NRO = {0}, SNAME = {1}, NAMEA = {2}, NAMEB = {3}, KAYNTIOS = {4}, ADDRESS = {5}, POSTA = {6}, POSTN = {7}, COMPANYN = {8}, COUNTRY = {9}, BID = {10}", item.NRO, item.SNAME, 
                        item.NAMEA, item.NAMEB, item.KAYNTIOS, item.ADDRESS, item.POSTA, item.POSTN, item.COMPANYN, 
                        item.COUNTRY, item.BID));
                }

我当前的代码只输出匹配的结果:

NRO  SNAME  NAMEA   NAMEB   IADDRESS  POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   BID
123  Fiat   Punto   500     J5        K4      O3      P4        O2         JT        S1
183  BMW    E64     SE0     JR        KE      OT      PG        OL         J8        U9

加入的输出应该是这样的(列顺序并不重要,只要它始终相同):

NRO  NRO1   SNAME  NAMEA   NAMEB   IADDRESS  POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   BID
123  423    Fiat   Punto   500     J5        K4      O3      P4        O2         JT        S1
133         Opel   Meriva  FTG     J5        K4      O3      P4        O2         JO        T3
153         MB     E200    C25     JN        KI      OP      PY        OR         JD        Y5
183  463    BMW    E64     SE0     JR        KE      OT      PG        OL         J8        U9
103         Audi   S6      700     JP        KU      OU      PN        OH         J6        I11
     483    KIA    E89     S78     J7        K7      O9      P6        O5         J4        U6

【问题讨论】:

标签: c# sql linq


【解决方案1】:

这里需要的是 Sql 中的Full Outer Join。但是因为它在Linq 中没有直接等价物,所以你应该这样实现它:T1 ⋃ (T2 - T1)

T1 : 由T1实现Left Join T2

(T2 - T1) : 由 T2 实现 Left Join T1 其中 T1 为空 p>

这应该会产生您正在寻找的结果:

// T1
var firstPart = from table1 in t1.AsEnumerable()
                join table2 in t2.AsEnumerable()
                    on (string)table1["SNAME"] equals (string)table2["SNAME"] into temp
                from table2 in temp.DefaultIfEmpty()
                select new
                {
                    NRO = (string)table1["NRO"],
                    NRO1 = table2 != null ? (string)table2["NRO"] : string.Empty,
                    SNAME = (string)table1["SNAME"],
                    NAMEA = (string)table1["NAMEA"],
                    NAMEB = (string)table1["NAMEB"],
                    ADDRESS = (string)table1["ADDRESS"],
                    POSTA = (string)table1["POSTA"],
                    POSTN = (string)table1["POSTN"],
                    POSTITP = (string)table1["POSTITP"],
                    COMPANYN = (string)table1["COMPANYN"],
                    COUNTRY = (string)table1["COUNTRY"],
                    BID = (string)table1["BID"]
                };

// (T2 -T1)
var secndPart = from table2 in t2.AsEnumerable()
                join table1 in t1.AsEnumerable()
                    on (string)table2["SNAME"] equals (string)table1["SNAME"] into temp
                from table1 in temp.DefaultIfEmpty()
                where table1 == null
                select new
                {
                    NRO = string.Empty,
                    NRO1 = (string)table2["NRO"],
                    SNAME = (string)table2["SNAME"],
                    NAMEA = (string)table2["NAMEA"],
                    NAMEB = (string)table2["NAMEB"],
                    ADDRESS = (string)table2["ADDRESS"],
                    POSTA = (string)table2["POSTA"],
                    POSTN = (string)table2["POSTN"],
                    POSTITP = (string)table2["POSTITP"],
                    COMPANYN = (string)table2["COMPANYN"],
                    COUNTRY = (string)table2["COUNTRY"],
                    BID = (string)table2["BID"]
                };

// T1 ⋃ (T2 - T1)
var results = firstPart.Concat(secndPart);

foreach (var item in results)
{
    Console.WriteLine(
        $"NRO = {item.NRO}, " +
        $"NRO1 = {item.NRO1}, " +
        $"SNAME = {item.SNAME}, " +
        $"NAMEA = {item.NAMEA}, " +
        $"NAMEB = {item.NAMEB}, " +
        $"ADDRESS = {item.ADDRESS}, " +
        $"POSTA = {item.POSTA}, " +
        $"POSTN = {item.POSTN}, " +
        $"POSTITP = {item.POSTITP}, " +
        $"COMPANYN = {item.COMPANYN}, " +
        $"COUNTRY = {item.COUNTRY}, " +
        $"BID = {item.BID}"
        );
}

【讨论】:

  • 完全没有 NRO1 = table2 != null ? (string)table2["NRO"] : string.Empty,null 异常。现在可以了!
  • 我可能应该问一个新问题,但我在想也许你有一个想法......只是注意到我又错过了一点。如何也从另一个表中添加值?我在原来的问题483 KIA E89 S78 J7 K7 O9 P6 O5 J4 U6 中又添加了一行。也要结果。不知何故,select new 还应该考虑未连接的 table2 列,不仅用于 NRO1,还用于输出到结果的其他列。这应该由另一个程序来完成吗?
  • @hatman:我现在在您更新的问题中看到的不再是Left Join。它在 sql 中是 Full Join,但在 Linq 中没有等价物。如果你想在 Linq 中这样做,你必须使用一个左连接和一个反向左连接来执行此操作并合并它们!我明天会更新我的答案以支持这个案例,但它不是很直接
  • 感谢您的帮助!现在我必须研究代码,以了解这种魔法是如何做到的,以便我自己在未来创造一些魔法!
  • @hatman:我更新了我的答案并尝试更详细地描述它。希望对你有帮助
猜你喜欢
  • 2015-05-28
  • 1970-01-01
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 2015-10-06
相关资源
最近更新 更多