【问题标题】:Building SQL with foreach使用 foreach 构建 SQL
【发布时间】:2018-05-16 06:32:02
【问题描述】:

我有这个代码:

private void button1_Click(object sender, EventArgs e)
{
    foreach(Int_String partner in partneri)
    {
        double danaBezProdaje = (DateTime.Today - Komercijalno.Partner.PoslednjaKupovina(partner._int)).TotalDays;
        if (danaBezProdaje > 31 && danaBezProdaje < 1100)
        {
            NeaktivniPartner np = new NeaktivniPartner();
            np.ppid = partner._int;
            np.naziv = partner._string;
            np.danaBezKupovine = danaBezProdaje;
            neaktivniPartneri.Add(np);
        }
    }
    dataGridView1.DataSource = M.List.ConvertToDataTable(neaktivniPartneri);
}

所以在这里我有List&lt;Int_String&gt; partneri,其中包含 5k 行。对于其中的每一个,我运行Komercijalno.Partner.PoslednjaKupovina(partner._int),其中包含如下所示的 SQL 语句:

public static DateTime PoslednjaKupovina(int ppid)        
{
    using (FbConnection con = new FbConnection(M.Baza.connectionKomercijalno2018))
    {
        con.Open();
        using (FbCommand cmd = new FbCommand("SELECT DATUM FROM DOKUMENT WHERE PPID = @PPID ORDER BY DATUM DESC", con))
        {
            cmd.Parameters.AddWithValue("@PPID", ppid);

            FbDataReader dr = cmd.ExecuteReader();

            if (dr.Read())
                return Convert.ToDateTime(dr[0]);
            else
                return new DateTime(1, 1, 1);
        }
    }
}

所以 SQL 语句执行了 5k 次,太慢了。

那么我如何将我的List&lt;Int_String&gt; 或只是整数数组传递给 sql 命令,以便我执行一次(在 foreach 内或其他方式)并返回dataAdapter,所以我只执行一次 SQL。

返回的 DataAdapter 应如下所示:

| ppid     | datum    |

假设我有表PARTNER(我用SELECT PPID, NAZIV FROM PARTNER填充列表partneri),其中包含以下数据:

| PPID    | NAZIV    |
| 1       | name001  |
| 2       | name002  |
| 3       | name003  |
| 4       | name004  |

假设我的 DOKUMENT 表有这些数据:

| ID      | PPID    | DATE       |
| 1       | 2       | 12.03.2018 |
| 2       | 3       | 12.03.2018 |
| 3       | 2       | 05.03.2018 |
| 4       | 2       | 03.04.2018 |
| 5       | 1       | 26.03.2018 |
| 6       | 4       | 21.02.2018 |
| 7       | 4       | 06.05.2018 |

我想要的输出是:

| PPID    | DATE       |
| 1       | 26.03.2018 |
| 2       | 03.04.2018 |
| 3       | 12.03.2018 |
| 4       | 06.05.2018 |

【问题讨论】:

  • 加入 ids by , 并在 where 子句中使用 in
  • 我应该如何将它传递给命令?
  • 不是一个好方法@Aria。参数字符串可能会在极限处出错,这样会导致性能不佳..
  • @HüseyinBurakKaradag,我认为限制超过了5k,但我不知道确切的限制,但它可以分隔in 的块?
  • @AleksaRistic 您在哪里填写“合作伙伴”数据?如果您在 DB 上获取数据,为什么要使用联接 DOKUMENT 表?如果您的答案是否定的,我的解决方案是,使用“批量插入”方法将 ids 数据插入会话临时表中,并将其与文档表连接。这要快得多

标签: c# sql winforms firebird


【解决方案1】:

您可以用一个查询替换所有逻辑:

select d.ppid, max(d.datum)
from partner p
inner join dokument d
    on d.ppid = p.ppid
group by d.ppid

您可能需要添加带有附加条件的where-clause 以选择您想要的合作伙伴。

【讨论】:

  • 还有一件事,而不是max(d.datum),我想成为`(DateTime.Today - max(d.datum)).TotalDays。我如何在查询中实现这一点
  • @AleksaRistic 您应该考虑将其保留在您的 C# 代码中,否则请考虑用另一个选择包装,例如 select ppid, datediff(day, datum, current_date) datedifference from (&lt;select from my answer&gt;) a
  • 为什么要嵌套选择?他不能把这个减法直接放到顶级选择中吗?而且,也许,我会从客户端发送DateTime.Today 作为参数。这样服务器会将其视为常量,并且因为本地日期时间在客户端计算机与服务器计算机上可能不同
  • 也许在这种特定情况下我不会使用DateDiff,而是直接使用DATE - DATE减法,如果需要,将datum列类型转换为类型。 firebirdtest.com/file/documentation/reference_manuals/…
  • @AleksaRistic 总体上在这个答案的 cmets 中你添加了两点,这是问题本身所遗漏的。您需要计算天数而不是日期,并且 - 重要的是 - 您的实际过滤不是一些任意的、随机的 ID 列表,而是真正的标准是 PARTNER.VIP=1。您从问题中省略了关键信息-您真正想要的信息,并且您得到的答案与您的实际问题不匹配-meta.stackexchange.com/questions/66377 /// 您的分数应该列在问题本身中,而不是 cmets !!!评论很吵,很难找到。
【解决方案2】:

将其作为答案,因为问题下方已经有很多 cmets,所以它只会在噪音中消失。

那么我如何将我的列表或整数数组传递给 sql 命令,以便我执行一次

这个问题在这里讨论过:Filter sql based on C# List instead of a filter table

根据查询的典型性(频率)和数据量,有几种方法。

  • 全局临时表
  • 使用UNION ALL和几个select {constants} from RDB$database模仿GTT
  • 将列表扁平化为一长串特殊格式并使用反向LIKE 匹配。

附言。对于您的特定任务,Mark 的答案肯定要好得多:您不必从服务器获取大量数据,只需将其传回另一个查询。我只是想链接一个与此问题的一部分相关的问题,该问题已经得到解答。

【讨论】:

    猜你喜欢
    • 2013-07-26
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 2014-09-02
    • 2017-07-30
    • 2011-03-18
    相关资源
    最近更新 更多