SQL IN()是否可以查询TAKE OR语句

时间:2019-04-27 22:22:55

标签: 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,或者说20个不可用,我希望能够在其位置选择19或21。 我该怎么办?我在IN语句中尝试了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

1 个答案:

答案 0 :(得分:1)

这是我想可以为您提供所需结果的查询。它使用分钟值的派生表,这些值之间的差最小,且为10分钟的最接近倍数。为了区分9和11,我们添加mn % 10 / 10,因此此查询的结果为(例如,分钟= 8、9、10、11、12):2.8、1.9、0、1.1、2.2。我们丢弃> 2的值,因为它们应该被忽略。然后,将此派生表JOIN添加到表中以从相应的行中选择数据:

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)

输出(用于我的demo on dbfiddle

id  mn  hr  dt          status
2   50  23  2019-04-19  1
12  1   0   2019-04-20  1
20  11  0   2019-04-20  1
27  19  0   2019-04-20  1

更新

例如,在有第9分钟和第11分钟的数据可用(但没有第10分钟)的情况下,此查询将偏爱第11分钟的值。可以通过更改来反转

 + (mn % 10 / 10)

收件人:

 - (mn % 10 / 10)

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

如您所见,它更喜欢59值而不是01值。

Updated dbfiddle

仅选择出现在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)

此查询的演示输出为:

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

Updated dbfiddle

更新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

updated demo的输出

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