我需要你的帮助。我尝试开发来自设备的消息监控,并面临SQL查询的一些问题。我有4个表的数据库:设备 - 消息 - 级别 - 操作。
设备: id,name; 操作: id,name; 级别: id,action_id,msgcount; 消息: id,action_id,device_id;
想法是每个设备发送有关不同操作的消息。此消息在“消息”表中注册。每个操作都有不同的级别,其中包含要获得此级别的消息数。我想计算已注册的消息并在UI进度中显示到下一级别和som additioonal信息。我使用以下查询:
select
mpd.action_id,
mpd.total,
lvl.id as lvl_id,
lvl.msgcount purpose,
lvl.name as level_name,
act.name as action
from
(select
mes.action_id,
count(1) total
from
messages mes,
devices dev
where
mes.device_id=dev.id
and dev.id=5
and mes.action_id not in(select
t.action_id
from
messages t
where
mes.device_id=t.device_id
and t.date > CURDATE())
group by
mes.action_id) mpd,
actions act,
levels lvl
where
mpd.action_id = act.id
and mpd.action_id = lvl.action_id
and lvl.msgcount = (SELECT
MIN(bad.msgcount)
FROM
levels lv
WHERE
lv.msgcount > mpd.total
and lv.action_id = mpd.action_id)
* mpd - messages pro device
但问题是如果顶层已经收到此动作,则列表中不再显示。但在这种情况下,我想显示最后收到的级别(最大)和消息总数。有人可以帮助我。
如果您提供一些建议如何改进我的查询,我将非常感激。
devices
|------|---------|
| id | name |
|------|---------|
| 3 | RH-SW-12|
| 5 | HRS-PR |
| 6 | PRS-PR |
|------|---------|
levels
|------|-----------|----------|--------|
| id | action_id | msgcount | name |
|------|-----------|----------|--------|
| 1 | 42 | 3 | low |
| 2 | 51 | 3 | start |
| 3 | 51 | 7 | medium |
| 4 | 51 | 15 | hight |
|------|-----------|----------|--------|
actions
|------|--------------|
| id | name |
|------|--------------|
| 42 | connection |
| 51 | stop service |
|------|--------------|
messages
|------|-------------|------------|----------------|
| id | action_id | device_id | date-time |
|------|-------------|------------|----------------|
| 1 | 42 | 3 |14.09.2017 08:51|
| 2 | 42 | 5 |14.09.2017 13:08|
| 3 | 42 | 5 |14.09.2017 16:30|
| 4 | 42 | 5 |15.09.2017 07:43|
| 5 | 51 | 3 |15.09.2017 07:50|
| 6 | 51 | 3 |15.09.2017 10:22|
| 7 | 51 | 3 |15.09.2017 15:11|
| 8 | 51 | 3 |15.09.2017 18:48|
| 9 | 51 | 3 |15.09.2017 19:03|
| 10 | 51 | 5 |15.09.2017 19:18|
| 11 | 42 | 5 |15.09.2017 21:33|
|------|-------------|------------|----------------|
我的查询现在将显示设备5的以下结果:
|------------|---------|----------|-----------|--------------|--------------|
| action_id | total | lvl_id | purpose | level_name | action |
|------------|---------|----------|-----------|--------------|--------------|
| 51 | 1 | 2 | 3 | start | stop service |
|------------|---------|----------|-----------|--------------|--------------|
没有关于动作42的信息,因为它没有更多级别。最后一级是“低”并达到了。 我想修改查询以获得设备5的下一个结果:
|------------|---------|----------|-----------|--------------|--------------|
| action_id | total | lvl_id | purpose | level_name | action |
|------------|---------|----------|-----------|--------------|--------------|
| 42 | 4 | 1 | 3 | low | connection |
| 51 | 1 | 2 | 3 | start | stop service |
|------------|---------|----------|-----------|--------------|--------------|
我希望有可能:)
答案 0 :(得分:1)
试试这个。这将为您提供当前水平。
SELECT
*
FROM
devices d,
actions a,
(SELECT
device_id, action_id, COUNT(1) AS count
FROM
messages
GROUP BY device_id , action_id) m,
levels l
WHERE
d.id = m.device_id
AND a.id = m.action_id
AND l.action_id = a.id
AND m.count >= l.msgcount
AND d.id = 5;
答案 1 :(得分:1)
有时与合适的人进行讨论有助于从另一方面审视问题。在尝试使用来自@HatimStovewala的答案的不同变体时,我找到了正确的解决方案:
SELECT
*
FROM
(SELECT
device_id, action_id, COUNT(1) AS count
FROM
messages
WHERE
device_id = 5
GROUP BY device_id , action_id) tmp,
levels lvl
WHERE
lvl.action_id = tmp.action_id
and lvl.msgcount = (SELECT
CASE COALESCE(MIN(msgcount),0) WHEN 0 THEN (SELECT MAX(msgcount) FROM levels WHERE action_id = tmp.action_id) ELSE MIN(repetitions) END AS rep
FROM
levels
WHERE
action_id=tmp.action_id
and msgcount >= tmp.count)
谢谢你,Hatim!