Php SQL IN()查询可以接受或语句吗
我有一个表名数据,如下所示。列mn从1到59运行,并从1开始 所以我有一个查询,它选择了10个这样的间隔Php SQL IN()查询可以接受或语句吗,php,mysql,Php,Mysql,我有一个表名数据,如下所示。列mn从1到59运行,并从1开始 所以我有一个查询,它选择了10个这样的间隔 SELECT * FROM data WHERE mn IN('00','10','20','30','40','50') AND dt='2019-04-20' ORDER BY ID ASC 这样做效果很好,可以得到所需的结果。 但由于某些原因,有时需要的数据00、10、20、30等不可用,我希望能够选择下一个或前一个来代替它 假设10不可用,我希望能够在其位置选择09或11,或者假设
SELECT * FROM data WHERE mn IN('00','10','20','30','40','50') AND dt='2019-04-20' ORDER BY ID ASC
这样做效果很好,可以得到所需的结果。
但由于某些原因,有时需要的数据00、10、20、30等不可用,我希望能够选择下一个或前一个来代替它
假设10不可用,我希望能够在其位置选择09或11,或者假设20不可用,我希望能够在其位置选择19或21。
我怎么能这样做呢?我试过一个OR,在语句中它返回了一个有趣的结果。
如果您有任何帮助,我们将不胜感激。谢谢
id mn dt status
---|---|----------|-----------
1 |01 |2019-04-20|1
2 |02 |2019-04-20|1
3 |03 |2019-04-20|1
4 |04 |2019-04-20|1
5 |05 |2019-04-20|1
6 |06 |2019-04-20|1
7 |07 |2019-04-20|1
8 |08 |2019-04-20|1
9 |09 |2019-04-20|1
10|10 |2019-04-20|1
11|11 |2019-04-20|1
12|12 |2019-04-20|1
13|13 |2019-04-20|1
14|14 |2019-04-20|1
15|15 |2019-04-20|1
16|16 |2019-04-20|1
17|17 |2019-04-20|1
18|18 |2019-04-20|1
19|19 |2019-04-20|1
20|21 |2019-04-20|1
21|22 |2019-04-20|1
22|23 |2019-04-20|1
这里有一个查询,我想它会给你你想要的结果。它使用分钟值的派生表,最小差值为10分钟的最近倍数。为了区分9和11,我们添加了
mn%10/10
,因此此查询的结果是(例如,对于分钟数=8,9,10,11,12):2.8,1.9,0,1.1,2.2。我们丢弃大于2的值,因为它们应该被忽略。然后将此派生表连接到表中,以从相应行中选择数据:
SELECT d.*
FROM data d
JOIN (SELECT IF(hr = 23 AND mn = 59, dt + INTERVAL 1 DAY, dt) AS date,
IF(mn = 59, (hr + 1) % 24, hr) AS hour,
((mn + 1) DIV 10) % 6 AS mn10,
MIN(LEAST(ABS(mn - mn DIV 10 * 10), ABS(mn - (mn + 9) DIV 10 * 10)) + (mn % 10 / 10)) AS mndiff
FROM data
GROUP BY date, hour, mn10
HAVING mndiff < 2) dd
ON dd.date = IF(d.hr = 23 AND d.mn = 59, d.dt + INTERVAL 1 DAY, d.dt)
AND dd.hour = IF(d.mn = 59, (d.hr + 1) % 24, d.hr)
AND dd.mn10 = ((d.mn + 1) DIV 10) % 6
AND dd.mndiff = LEAST(ABS(d.mn - d.mn DIV 10 * 10), ABS(d.mn - (d.mn + 9) DIV 10 * 10)) + (d.mn % 10 / 10)
更新
例如,如果第9分钟和第11分钟的数据可用(但第10分钟不可用),此查询将支持第11分钟的值。这可以通过改变
+ (mn % 10 / 10)
致:
及
如您所见,与01
值相比,它更喜欢59
值
仅选择在10分钟标记时或之前出现的值(例如,按优先顺序选择10,9,8,7),您可以将查询简化为:
SELECT d.*
FROM data d
JOIN (SELECT IF(hr = 23 AND mn >= 57, dt + INTERVAL 1 DAY, dt) AS date,
IF(mn >= 57, (hr + 1) % 24, hr) AS hour,
((mn + 3) DIV 10) % 6 AS mn10,
MIN(ABS(mn - (mn + 9) DIV 10 * 10)) AS mndiff
FROM data
GROUP BY date, hour, mn10
HAVING mndiff <= 3) dd
ON dd.date = IF(d.hr = 23 AND d.mn >= 57, d.dt + INTERVAL 1 DAY, d.dt)
AND dd.hour = IF(d.mn >= 57, (d.hr + 1) % 24, d.hr)
AND dd.mn10 = ((d.mn + 3) DIV 10) % 6
AND dd.mndiff = ABS(mn - (mn + 9) DIV 10 * 10)
更新2
根据评论中的其他反馈,时间显示为最近10分钟标记的时间,而不是原始时间。这将导致对查询的微小更改:
SELECT dd.mn10 * 10 AS mn, dd.hour, dd.date, d.status, d.id
FROM data d
JOIN (SELECT IF(hr = 23 AND mn >= 57, dt + INTERVAL 1 DAY, dt) AS date,
IF(mn >= 57, (hr + 1) % 24, hr) AS hour,
((mn + 3) DIV 10) % 6 AS mn10,
MIN(ABS(mn - (mn + 9) DIV 10 * 10)) AS mndiff
FROM data
GROUP BY date, hour, mn10
HAVING mndiff <= 3) dd
ON dd.date = IF(d.hr = 23 AND d.mn >= 57, d.dt + INTERVAL 1 DAY, d.dt)
AND dd.hour = IF(d.mn >= 57, (d.hr + 1) % 24, d.hr)
AND dd.mn10 = ((d.mn + 3) DIV 10) % 6
AND dd.mndiff = ABS(mn - (mn + 9) DIV 10 * 10)
ORDER BY dd.date, dd.hour, mn
如果9、10和11都不可用怎么办?这是一种可能的情况吗?如果9、10、11不可用,那么它将被忽略。我只需要能够在之前或之后选择一个,这就是@nick。你能解释一下“mn”是什么吗?如果它是某个列表的外键,那么可以使用左连接和合并。如果这是一个平面文件,那就难多了。请确认一下,在id=60
和id=120
等地方。,mn
将恢复到1
并重新开始计数?是的,尼克,因为mn实际上是分钟,所以从59到00,然后到01等等@Nickthanks我生病了,这就是为什么你没有听到我的消息。这个查询将帮助很大,我会标记它。但尼克我注意到,这个问题在之后而不是之前最受欢迎。例如,如果9和11可用,它将首先选择11而不是9。但我认为可能会有一个解决办法。再说一次,如果我只考虑之前,而不考虑之后,那么如果10个id不可用,那么可以选择7、8、9个?@Donsplash很抱歉听到这个消息-希望你完全康复。我用两个新的查询更新了我的帖子:第一个将支持9值而不是11,第二个将只从之前(按照优先顺序为10、9、8、7)中进行选择,而不是在之后。Nick您的解决方案有效,谢谢,最后一个问题和帮助。谢谢你问我现在好多了。尼克,如果我选择7而不是10。我如何使其显示10作为mn字段,但将使用值7,在20的情况下,可能我使用19代替20,因为20不可用。我如何返回结果显示20,并根据情况使用值19。最后,如果我想容纳多达456789的数据,我可以将最后一个查询编辑为mn>=52。谢谢尼克的帮助。@Donsplash关于第一个问题,只需将选择d.*
更改为选择dd.mn10*10作为mn,d.hr,d.dt,d.status
。我不知道你说的第二个是什么意思?如果mn增加到一个大的数字,小时字段是什么样子的?你好,尼克,当我这样做时,如更改的选择d.*选择dd.mn10*10作为mn,d.hr,d.dt,d.status我在字段列表中得到一个错误无效列dd。我在第二个问题上的意思是,如果我可以在案例10中容纳值4、5、6、7、8、9,或者任何其他更接近的值,则不可用,谢谢您的帮助。
HAVING mndiff < 2
HAVING mndiff < 1
SELECT d.*, dd.*
FROM data d
JOIN (SELECT IF(hr = 23 AND mn = 59, dt + INTERVAL 1 DAY, dt) AS date,
IF(mn = 59, (hr + 1) % 24, hr) AS hour,
((mn + 1) DIV 10) % 6 AS mn10,
MIN(LEAST(ABS(mn - mn DIV 10 * 10), ABS(mn - (mn + 9) DIV 10 * 10)) - (mn % 10 / 10)) AS mndiff
FROM data
GROUP BY date, hour, mn10
HAVING mndiff < 1) dd
ON dd.date = IF(d.hr = 23 AND d.mn = 59, d.dt + INTERVAL 1 DAY, d.dt)
AND dd.hour = IF(d.mn = 59, (d.hr + 1) % 24, d.hr)
AND dd.mn10 = ((d.mn + 1) DIV 10) % 6
AND dd.mndiff = LEAST(ABS(d.mn - d.mn DIV 10 * 10), ABS(d.mn - (d.mn + 9) DIV 10 * 10)) - (d.mn % 10 / 10)
id mn hr dt status
2 50 23 2019-04-19 1
11 59 23 2019-04-19 1
20 11 0 2019-04-20 1
27 19 0 2019-04-20 1
SELECT d.*
FROM data d
JOIN (SELECT IF(hr = 23 AND mn >= 57, dt + INTERVAL 1 DAY, dt) AS date,
IF(mn >= 57, (hr + 1) % 24, hr) AS hour,
((mn + 3) DIV 10) % 6 AS mn10,
MIN(ABS(mn - (mn + 9) DIV 10 * 10)) AS mndiff
FROM data
GROUP BY date, hour, mn10
HAVING mndiff <= 3) dd
ON dd.date = IF(d.hr = 23 AND d.mn >= 57, d.dt + INTERVAL 1 DAY, d.dt)
AND dd.hour = IF(d.mn >= 57, (d.hr + 1) % 24, d.hr)
AND dd.mn10 = ((d.mn + 3) DIV 10) % 6
AND dd.mndiff = ABS(mn - (mn + 9) DIV 10 * 10)
id mn hr dt status
2 50 23 2019-04-19 1
11 59 23 2019-04-19 1
19 8 0 2019-04-20 1
27 19 0 2019-04-20 1
33 27 0 2019-04-20 1
SELECT dd.mn10 * 10 AS mn, dd.hour, dd.date, d.status, d.id
FROM data d
JOIN (SELECT IF(hr = 23 AND mn >= 57, dt + INTERVAL 1 DAY, dt) AS date,
IF(mn >= 57, (hr + 1) % 24, hr) AS hour,
((mn + 3) DIV 10) % 6 AS mn10,
MIN(ABS(mn - (mn + 9) DIV 10 * 10)) AS mndiff
FROM data
GROUP BY date, hour, mn10
HAVING mndiff <= 3) dd
ON dd.date = IF(d.hr = 23 AND d.mn >= 57, d.dt + INTERVAL 1 DAY, d.dt)
AND dd.hour = IF(d.mn >= 57, (d.hr + 1) % 24, d.hr)
AND dd.mn10 = ((d.mn + 3) DIV 10) % 6
AND dd.mndiff = ABS(mn - (mn + 9) DIV 10 * 10)
ORDER BY dd.date, dd.hour, mn
mn hour date status id
0 23 2019-04-19 1 12
50 23 2019-04-19 1 2
0 0 2019-04-20 1 11
10 0 2019-04-20 1 20
20 0 2019-04-20 1 28
30 0 2019-04-20 1 34