gpt4 book ai didi

mysql - 条件SQL查询协助

转载 作者:行者123 更新时间:2023-11-28 23:08:52 25 4
gpt4 key购买 nike

问题
对于下面提供的所有内容、所有示例和数据,是否有其他方法可以通过执行不同表的UNION来获得预期结果?
我的麻烦
基本上我需要有条件逻辑来:
如果在定义的时间段内找到记录,则从表中获取所有记录(多个)
如果在定义的时间段内找不到记录,则从表中获取自
规定时间段
台阶
只需创建表并插入下面列出的数据和该逻辑,然后运行我在每个示例中提供的每个查询,就可以轻松模拟我所指的内容。
上下文和说明
也许用一个temp/memory表代替@Now~变量,在相关的temp表中有TRUE条件,或者用一些详细的(或者对某些简单的)数据表UNION方法?
我指的是下面的一个“定义的时间段”,或者是意思相近的词,通过这些词,我指的是一个特定的开始时间和一个特定的结束时间,以及这两点之间的所有时间,这就是我使用这个词时所说的。
有一个报告系统可以生成这些开始和结束时间框架,我已经在一个存储过程中获得了逻辑,这个存储过程被调用,日期时间被传入。
我只提供了存储过程的一部分,并对其进行了一些选择查询,以给出问题的示例以及预期或需要的结果。
创建数据
使用下面的命令,您可以在MySQL数据库中创建三个表,这也将填充我在运行的查询中使用的数据,以便在每个查询的下面显示结果,这样您就可以跟踪并使用数据,甚至可以帮助我找到解决方案或一两个指针。
注意:在确定将MySQL实例上的JOIN更改为实际的DB名称或模式之前。

USE <DBName>; 
CREATE TABLE `ponumber` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));

CREATE TABLE `batch_number` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));

CREATE TABLE `batchweight` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));

INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 10:47:55',0);
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',1217911);
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:24:18',1217906);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:18',5522);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:25:33',5521);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 11:44:45',5520);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:05',5519);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:22:58',5518);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:19',38985);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',38985);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:23:03',31002);

查询1
USE <DBName>; 

SET @bStartTime = '2017-09-29 11:10:00';
SET @bEndTime = '2017-09-29 12:48:00';

SELECT TimeStr, CONCAT('Set Load Number: ',Value) AS Value
FROM ponumber
WHERE TimeStr BETWEEN @bStartTime AND @bEndTime

UNION

SELECT TimeStr, CONCAT('Set Batch Number: ',Value) AS Value
FROM batch_number
WHERE TimeStr BETWEEN @bStartTime AND @bEndTime

UNION

SELECT TimeStr,
CONCAT('Batch Weight: ',Value) AS Value
FROM batchweight
WHERE TimeStr BETWEEN @bStartTime AND @bEndTime

ORDER BY TimeStr;

查询一个结果
enter image description here
如您所见,没有 <DBName>是因为 Set Load Number表中没有来自定义时间段的 PONumber@bStartTime变量定义的时间的记录。
如果在定义的时间段内 @bEndTime表中没有数据记录,那么结果应该列出该表中的最新记录,甚至那些不在定义的时间段内的记录,因此我构建了查询2。
问题二
USE <DBName>; 
SET @bStartTime = '2017-09-29 11:10:00';
SET @bEndTime = '2017-09-29 12:48:00';

SET @LastPONumber = (SELECT Value FROM PONumber ORDER BY TimeStr DESC LIMIT 1);
SET @NowPONumber = (SELECT Value FROM PONumber WHERE TimeStr BETWEEN @bStartTime AND @bEndTime ORDER BY TimeStr DESC LIMIT 1);
SET @LastPONumTimeStr = (SELECT TimeStr FROM PONumber ORDER BY TimeStr DESC LIMIT 1);
SET @NowPONumTimeStr = (SELECT TimeStr FROM PONumber WHERE TimeStr BETWEEN @bStartTime AND @bEndTime ORDER BY TimeStr DESC LIMIT 1);

SELECT DISTINCT TimeStr, Value FROM
(SELECT
CASE
WHEN TimeStr = 1 THEN
(SELECT @NowPONumTimeStr AS TimeStr)
ELSE
(SELECT @LastPONumTimeStr AS TimeStr)
END AS TimeStr,
CASE
WHEN Value = 1 THEN
(SELECT (CONCAT('Set Load Number: ',@NowPONumber)) AS Value)
ELSE
(SELECT (CONCAT('Set Load Number: ',@LastPONumber)) AS Value)
END AS Value
FROM PONumber) AS X

UNION

SELECT TimeStr, CONCAT('Set Batch Number: ',Value) AS Value
FROM batch_number
WHERE TimeStr BETWEEN @bStartTime AND @bEndTime

UNION

SELECT TimeStr,
CONCAT('Batch Weight: ',Value) AS Value
FROM batchweight
WHERE TimeStr BETWEEN @bStartTime AND @bEndTime

ORDER BY TimeStr;

查询二结果
enter image description here
因此,查询2是我创建 PONumber@LastPONumber@NowPONumber@LastPONumTimeStr变量的地方,根据使用 @NowPONumTimeStr表达式的条件,使用 SELECTORDER BY DESC将这些值设置为 LIMIT 1查询结果。
现在的结果显示了最近的 CASE WHEN表记录,因为在定义的时间段之间找不到任何记录,所以这允许它在定义的时间段之外进一步返回。
现在,如果在定义的时间段内 PONumber表中没有数据记录,则需要列出最近的记录,就像在查询2中对 Batch_Number表所做的那样,所以我使用与查询2用于 PONumber表的相同条件 CASE WHEN逻辑等来构建查询3。
问题三
USE <DBName>; 
SET @bStartTime = '2017-09-29 11:10:00';
SET @bEndTime = '2017-09-29 12:48:00';

## - PONumber Table Variables
SET @LastPONumber = (SELECT Value FROM PONumber ORDER BY TimeStr DESC LIMIT 1);
SET @NowPONumber = (SELECT Value FROM PONumber WHERE TimeStr BETWEEN @bStartTime AND @bEndTime ORDER BY TimeStr DESC LIMIT 1);
SET @LastPONumTimeStr = (SELECT TimeStr FROM PONumber ORDER BY TimeStr DESC LIMIT 1);
SET @NowPONumTimeStr = (SELECT TimeStr FROM PONumber WHERE TimeStr BETWEEN @bStartTime AND @bEndTime ORDER BY TimeStr DESC LIMIT 1);

## - Batch_Number Table Variables
SET @LastBatNumber = (SELECT Value FROM Batch_Number ORDER BY TimeStr DESC LIMIT 1);
SET @NowBatNumber = (SELECT Value FROM Batch_Number WHERE TimeStr BETWEEN @bStartTime AND @bEndTime ORDER BY TimeStr DESC LIMIT 1);
SET @LastBatNumTimeStr = (SELECT TimeStr FROM Batch_Number ORDER BY TimeStr DESC LIMIT 1);
SET @NowBatNumTimeStr = (SELECT TimeStr FROM Batch_Number WHERE TimeStr BETWEEN @bStartTime AND @bEndTime ORDER BY TimeStr DESC LIMIT 1);

SELECT DISTINCT TimeStr, Value FROM
(SELECT
CASE
WHEN TimeStr = 1 THEN
(SELECT @NowPONumTimeStr AS TimeStr)
ELSE
(SELECT @LastPONumTimeStr AS TimeStr)
END AS TimeStr,
CASE
WHEN Value = 1 THEN
(SELECT (CONCAT('Set Load Number: ',@NowPONumber)) AS Value)
ELSE
(SELECT (CONCAT('Set Load Number: ',@LastPONumber)) AS Value)
END AS Value
FROM PONumber) AS X

UNION

SELECT DISTINCT TimeStr, Value FROM
(SELECT
CASE
WHEN TimeStr = 1 THEN
(SELECT @NowBatNumTimeStr AS TimeStr)
ELSE
(SELECT @LastBatNumTimeStr AS TimeStr)
END AS TimeStr,
CASE
WHEN Value = 1 THEN
(SELECT (CONCAT('Set Batch Number: ',@NowBatNumber)) AS Value)
ELSE
(SELECT (CONCAT('Set Batch Number: ',@LastBatNumber)) AS Value)
END AS Value
FROM Batch_Number) AS X

UNION

SELECT TimeStr,
CONCAT('Batch Weight: ',Value) AS Value
FROM batchweight
WHERE TimeStr BETWEEN @bStartTime AND @bEndTime

ORDER BY TimeStr;

查询三结果
enter image description here
当查询3的结果检测到 PONumber表在定义的时间段之间确实有记录时,它只列出最近的一条记录,而不列出查询2结果中显示的其他两个批号值( Batch_Number)。这显然是因为 5521, and 5520查询变量只包含最近的1条记录。
问题
我需要能够检查
定义时间段并执行以下两项操作之一:
如果在该时间段之间存在记录,则列出所有记录,而不只是最近的一条记录。
如果在定义的时间段之间找不到任何记录,请进一步查看该时间段之外的记录,并列出最近的一条记录
本质上,对于 @NowBatNumber表以及我在查询3中尝试的方式,我希望结果看起来与查询2的结果完全相同,并且仍然使用条件逻辑来显示否则需要什么。
回去,再把这个问题读一遍,因为它现在可能更有意义了。

最佳答案

短而简单的问题比长而复杂的问题更容易引起注意这并不是因为我们回答不了,而是因为我们的问题太多,志愿者的时间太少,所以很难证明有足够的时间来阅读大问题。
不过,我认为你的基本要求并不复杂。您需要一种方法来检索属于某个时间范围内的行,或者如果不在该范围内,则提供离该范围最近的行。
在支持ROW_NUMBER()OVER()的数据库中,这非常简单(MySQL 8.x计划支持这一点),但在模拟ROW_NUMBER()之前,可以使用变量和有序子查询。
您可以在SQL Fiddle试用此解决方案
MySQL 5.6模式设置:

CREATE TABLE `ponumber` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));

INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 10:47:55',0);
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',1217911);
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:24:18',1217906);

CREATE TABLE `batch_number` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));

INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:18',5522);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:25:33',5521);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 11:44:45',5520);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:05',5519);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:22:58',5518);

CREATE TABLE `batchweight` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));

INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:19',38985);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',38985);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:23:03',31002);

查询:
SET @bStartTime  := '2017-09-29 11:10:00'   
SET @bEndTime := '2017-09-29 12:48:00'

SELECT
SrcTable, TimeStr, Value
FROM (
SELECT
@row_num :=IF( @prev_value=u.SrcTable, @row_num + 1 ,1) AS RowNumber
, u.*
, @prev_value := u.SrcTable
FROM (

select 'ponumber' SrcTable , TimeStr, `Value`
from ponumber
union all
select 'batch_number' SrcTable , TimeStr, `Value`
from batch_number
union all
select 'batchweight' SrcTable , TimeStr, `Value`
from batchweight
) u
CROSS JOIN (SELECT @row_num := 1, @prev_value :='') vars
ORDER BY SrcTable, TimeStr DESC
) d
WHERE (d.TimeStr between @bStartTime and @bEndTime)
OR (TimeStr < @bStartTime AND RowNumber = 1)

因此,这将计算一个“RowNumber”,每个源表的最新行从1开始。然后,该派生表将按时间范围筛选,如果不在时间范围内,则按行号筛选。
另请注意,我没有使用 UNION,而是使用了 UNION ALL。在性能上有很大的差异,应该学会根据需要使用每一个。如果使用 UNION也不要使用 select distinct,因为你只是在浪费精力。
Results
|     SrcTable |              TimeStr | Value |
|--------------|----------------------|-------|
| batchweight | 2017-09-29T12:46:19Z | 38985 |
| batch_number | 2017-09-29T12:46:18Z | 5522 |
| batch_number | 2017-09-29T12:25:33Z | 5521 |
| batch_number | 2017-09-29T11:44:45Z | 5520 |
| ponumber | 2017-09-28T10:47:55Z | 0 |

关于mysql - 条件SQL查询协助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46495242/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com