我有一个SQL查询完全如this post所述.总而言之,它将读取所有带有偏移量指定的Carboards.此查询在MariaDB数据库上执行.
现在,我在我的C#ASP.NET程序中有我的Cardboards(ID,Cardboard_number,DateTime,ProductionLineNode).我必须阅读每个Carboard的所有生产过程(基本上production. start = cardboard. datetime = production. end).<<

Oracle数据库中Productions的表如下所示(我没有自己创建该表,也无法更改任何内容,因为它也用于生产程序):

  • 生产编号(编号)
  • POSNR(数字)
  • DateTime(时间戳(6))
  • PROJECT_ACTIVE(1)
  • 生产线(编号)

PROCESS_ACTIVE列用作标志,当启动生产流程时,一行插入DATETIME = sysdate,PROCESS_ACTIVE = 1,停止的行用sysdate,PROCESS_ACTIVE = 0表示.

我已经创建了一个查询来总结我的过程,所以我得到了每个Productivity_NUMBER和POSNR的开始和结束:

SELECT * 
FROM
(
    SELECT PRODUCTION_NUMBER, POSNR, PROCESS_ACTIVE, PRODUCTION_LINE, DATETIME as START, LEAD(DATETIME, 1, SYSDATE) OVER (ORDER BY DATETIME ASC) AS END
    FROM ssq_lauftr
    GROUP BY PRODUCTION_NUMBER, POSNR, PROCESS_ACTIVE, PRODUCTION_LINE, DATETIME
    ORDER BY DATETIME 
)
WHERE PROCESS_ACTIVE = 1

我在C#代码中遍历从MariaDB检索到的所有Cardboards,并执行这个查询为every cardboard(其中cardboard是从C#循环注入的对象):

SELECT * 
FROM
(
    SELECT PRODUCTION_NUMBER, POSNR, PROCESS_ACTIVE, PRODUCTION_LINE, DATETIME as START, LEAD(DATETIME, 1, SYSDATE) OVER (ORDER BY DATETIME ASC) AS END
    FROM ssq_lauftr
    WHERE PRODUCTION_LINE = cardboard.PRODUCTION_LINENUMBER and DATETIME <= cardboard.DATETIME
    GROUP BY PRODUCTION_NUMBER, POSNR, PROCESS_ACTIVE, PRODUCTION_LINE, DATETIME
    ORDER BY DATETIME 
)
WHERE PROCESS_ACTIVE = 1 AND cardboard.DATETIME <= END

它在少量的纸板上工作得很好.

这个解决方案的问题是,如果我有很多Cardboard,阅读所有Productions的整个功能将花费太长的时间.有没有一种方法(例如使用PLSQL)使这个过程更有效?上面的SQL语句相当快,但是在C#中迭代列表并将结果添加到ProductionSet中会大大降低应用程序的速度.

Edit:
纸板存储在MariaDB中,而Productions存储在Oracle DB中. 我当前的C#代码描述的功能看起来像这样:

Cardboards = [.. _mariaDB.Cardboards.FromSql($@"
    SET @cb_num = {request.Cardboard_Number};
    select *
    from (
        SELECT *,
        sum(Cardboard_Number LIKE CONCAT(@cb_num, '%')) over (
            partition by ProductionLine_Number
            order by timestamp, id
            rows BETWEEN {CardboardOffset} preceding AND {CardboardOffset} following
        ) matches
        from cardboards
    ) cardboards_with_matches
    where matches
")];

HashSet<Production> productionSet = [];

for(int i = 0; i < Cardboards.Count(); i++)
{
    productionSet.UnionWith(_oracleDB.Production.FromSqlRaw($@"
        SELECT * 
        FROM
        (
            SELECT PRODUCTION_NUMBER, POSNR, PROCESS_ACTIVE, PRODUCTION_LINE, DATETIME as START, LEAD(DATETIME, 1, SYSDATE) OVER (ORDER BY DATETIME ASC) AS END
            FROM Productions
            WHERE PRODUCTION_LINE = {Cardboards.ElementAt(i).ProductionLine_Number} and {Cardboards.ElementAt(i).DateTime} <= cardboard.DATETIME
            GROUP BY PRODUCTION_NUMBER, POSNR, PROCESS_ACTIVE, PRODUCTION_LINE, DATETIME
            ORDER BY DATETIME 
        )
        WHERE PROCESS_ACTIVE = 1 AND {Cardboards.ElementAt(i).DateTime} <= END
    "));
}

MariaDB fiddle - Fiddle for Cardboards
OracleDB fiddle - Fiddle for Productions (not running in fiddle, but running in Oracle SQL developer, I honestly don't know the problem there)

为了详细分析,基本上当用户搜索Cardboard 'WDL—005943998—1'时,预期输出将是整个Cardboard的数据(在MariaDB中搜索)和Productivity_NUMBER = 461618的生产数据,因为Cardboard的日期时间介于生产开始和结束之间,并且生产与Cardboard扫描的同一行上.

请注意,可以有相同的生产多次,但具有不同的时间戳(例如,生产暂停).

推荐答案

如果你有两个表:都在Oracle数据库中;或者有MariaDB数据库可以从Oracle数据库访问(即通过数据库链接),那么你可以使用查询找到这两个表之间的所有关系:

WITH production_bounds (production_number, posnr, process_active, production_line, start_dt, end_dt) AS (
  SELECT PRODUCTION_NUMBER,
         POSNR,
         PROCESS_ACTIVE,
         PRODUCTION_LINE,
         DATETIME as start_dt,
         LEAD(DATETIME, 1, SYSTIMESTAMP) OVER (
           PARTITION BY production_line
           ORDER BY DATETIME ASC
         ) AS end_dt
  FROM   productions
)
SELECT p.production_number,
       p.posnr,
       p.process_active,
       p.production_line,
       p.start_dt,
       p.end_dt,
       c.id,
       c.cardboard_number
FROM   production_bounds p
       INNER JOIN cardboard c
       ON     p.production_line = c.productionline_number
          AND c.date_time BETWEEN p.start_dt AND p.end_dt

其中,对于示例数据(Oracle中的两个表):

CREATE TABLE cardboard
(
    id int,
    Cardboard_Number varchar2(100),
    date_Time TIMESTAMP(0),
    ProductionLine_Number int
);

INSERT INTO cardboard VALUES 
(2,'WDL-005943998-1', TIMESTAMP '2014-08-05 10:03:32', 1),
(4,'spL1ml82N4o',TIMESTAMP '2024-02-29 17:13:54', 1),
(5,'WDL-005943998-1',TIMESTAMP '2024-03-01 09:44:42', 1),
(6,'WDL-005943998-1',TIMESTAMP '2024-03-01 10:34:57', 1),
(7,'950024027237',TIMESTAMP '2024-03-01 10:44:57', 1),
(8,'950024027237',TIMESTAMP '2024-03-01 10:52:57', 1),
(9,'WDL-005943998-1',TIMESTAMP '2024-03-01 13:58:43', 2),
(10,'WDL-005943998-1',TIMESTAMP '2024-03-01 13:58:46', 2),
(11,'spL1ml82N4o',TIMESTAMP '2024-03-01 14:09:43', 2),
(12,'WDL-005943998-1',TIMESTAMP '2024-03-12 15:48:36', 2);

CREATE TABLE Productions
(   
  PRODUCTION_NUMBER NUMBER, 
  POSNR NUMBER, 
  DATETIME  TIMESTAMP(0), 
  PROCESS_ACTIVE VARCHAR2(1),
  PRODUCTION_LINE NUMBER
);

BEGIN
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461793, 1, TO_TIMESTAMP('2014-08-04 09:01:41', 'YYYY-MM-DD HH24:MI:SS'), '1', 1);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461793, 1, TO_TIMESTAMP('2014-08-04 11:01:41', 'YYYY-MM-DD HH24:MI:SS'), '0', 1);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461618, 2, TO_TIMESTAMP('2014-08-05 10:01:41', 'YYYY-MM-DD HH24:MI:SS'), '1', 1);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461619, 2, TO_TIMESTAMP('2014-08-05 10:02:46', 'YYYY-MM-DD HH24:MI:SS'), '1', 2);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461618, 2, TO_TIMESTAMP('2014-08-05 10:05:09', 'YYYY-MM-DD HH24:MI:SS'), '0', 1);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461619, 2, TO_TIMESTAMP('2014-08-05 10:07:46', 'YYYY-MM-DD HH24:MI:SS'), '0', 2);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461818, 1, TO_TIMESTAMP('2014-08-14 22:53:12', 'YYYY-MM-DD HH24:MI:SS'), '1', 1);
INSERT INTO Productions(PRODUCTION_NUMBER, POSNR, DATETIME, PROCESS_ACTIVE, PRODUCTION_LINE)
  VALUES (461818, 1, TO_TIMESTAMP('2014-08-14 23:25:30', 'YYYY-MM-DD HH24:MI:SS'), '0', 1);
END;
/

输出:

PRODUCTION_NUMBER POSNR PROCESS_ACTIVE PRODUCTION_LINE START_DT END_DT ID CARDBOARD_NUMBER
461618 2 1 1 2014-08-05 10:01:41. 2014-08-05 10:05:09.000000 2 WDL-005943998-1
461818 1 0 1 2014-08-14 23:25:30. 2024-03-28 12:53:28.569815 4 spL1ml82N4o
461818 1 0 1 2014-08-14 23:25:30. 2024-03-28 12:53:28.569815 5 WDL-005943998-1
461818 1 0 1 2014-08-14 23:25:30. 2024-03-28 12:53:28.569815 6 WDL-005943998-1
461818 1 0 1 2014-08-14 23:25:30. 2024-03-28 12:53:28.569815 7 950024027237
461818 1 0 1 2014-08-14 23:25:30. 2024-03-28 12:53:28.569815 8 950024027237
461619 2 0 2 2014-08-05 10:07:46. 2024-03-28 12:53:28.569815 9 WDL-005943998-1
461619 2 0 2 2014-08-05 10:07:46. 2024-03-28 12:53:28.569815 10 WDL-005943998-1
461619 2 0 2 2014-08-05 10:07:46. 2024-03-28 12:53:28.569815 11 spL1ml82N4o
461619 2 0 2 2014-08-05 10:07:46. 2024-03-28 12:53:28.569815 12 WDL-005943998-1

如果您想搜索具有特定cardboard_number的活动行,请添加这些筛选器:

WITH production_bounds (production_number, posnr, process_active, production_line, start_dt, end_dt) AS (
  SELECT PRODUCTION_NUMBER,
         POSNR,
         PROCESS_ACTIVE,
         PRODUCTION_LINE,
         DATETIME as start_dt,
         LEAD(DATETIME, 1, SYSTIMESTAMP) OVER (
           PARTITION BY production_line
           ORDER BY DATETIME ASC
         ) AS end_dt
  FROM   productions
)
SELECT p.production_number,
       p.posnr,
       p.process_active,
       p.production_line,
       p.start_dt,
       p.end_dt,
       c.id,
       c.cardboard_number
FROM   production_bounds p
       INNER JOIN cardboard c
       ON     p.production_line = c.productionline_number
          AND c.date_time BETWEEN p.start_dt AND p.end_dt
WHERE  cardboard_number = 'WDL-005943998-1'
AND    process_active = 1

输出:

PRODUCTION_NUMBER POSNR PROCESS_ACTIVE PRODUCTION_LINE START_DT END_DT ID CARDBOARD_NUMBER
461618 2 1 1 2014-08-05 10:01:41. 2014-08-05 10:05:09.000000 2 WDL-005943998-1

fiddle

Csharp相关问答推荐

如何从顶部提取发票号作为单词发票后的第一个匹配

在WPF.NET 6中使用C++/WinRT组件(但实际上是任何WinRT组件)

为什么Blazor值在更改后没有立即呈现?

. NET 8控制台应用程序DI错误无法解析Microsoft. Extension. Logging. ILoggerFactory类型的服务'''

无法通过绑定禁用条目

在ASP.NET Core Web API项目中通过中间件修改`Request.Path`不会更改使用的控制器/操作

如何使用NumberFormatInfo

使用泛型可空类实现接口

Blazor Web App WASM的两个独立项目令人困惑

是否有必要在ASP.NET Core中注册可传递依赖项?

在C#中过滤Excel文件

MSTest--将消息直接写入StdOut和使用TestContext有什么不同?

WPF DataGrid文件名列,允许直接输入文本或通过对话框按键浏览

源代码生成器:CS8795分部方法';Class1.GetS2(字符串)';必须有实现部分,因为它有可访问性修饰符?

MudBlazor Textfield已禁用,但其验证工作正常

当我try 在与XAMP的MySQL服务器连接的ASP.NET核心应用程序中添加迁移时出现错误

为什么C#/MSBuild会自发地为不同的项目使用不同的输出路径?

两个DateTimeOffset之间的差异返回意外的负值

如何在Xamarin.Forms中检索PanGesture事件的位置?

身份验证中间件如何处理多个方案