[英]How to write a better SQL for this scenario
I have a table called " DEVICE " which contains these columns: 我有一个名为“ DEVICE ”的表,其中包含以下列:
------------------------------------------
SN | User_ID | State | ...
------------------------------------------
1 | 1001 | deployed | ...
2 | 1001 | deploying | ...
3 | 1002 | inventory | ...
4 | 1003 | deploying | ...
5 | 1001 | deploying | ...
6 | 1002 | synced | ...
7 | 1002 | synced | ...
8 | 1010 | synced | ...
9 | 1008 | unsynced | ...
---------------------------------------
As you can see, this table lists all the devices, which are belong to different user by their user_id. 如您所见,此表列出了所有设备,这些设备按其user_id属于不同的用户。 Also for all these devices, their state is one of these 5 types:
同样对于所有这些设备,它们的状态是以下5种类型之一:
"inventory",
"deployed",
"deploying",
"synced"
"unsynced".
I need a SQL Query that returns back the user_id that holds the maximum devices of each individual State. 我需要一个SQL查询,该查询返回的user_id包含每个州的最大设备数。 For example, for the above set of data in the first table, the return would be:
例如,对于第一个表中的上述数据集,返回为:
-----------------------------------------------------------
User_ID | State | Maximum
-----------------------------------------------------------
1001 | deployed | 1
1001 | deploying| 2
1002 | inventory| 1
1002 | synced | 2
1008 | unsynced | 1
------------------------------------------------------------
The SQL I have created so far is like this: 到目前为止,我创建的SQL是这样的:
SELECT
STATE, ACCOUNT, CNT
from
( select account_id as ACCOUNT, state as STATE, count(*) as CNT
from DEVICE group by account_id, state ) T1
where
( STATE, CNT )
IN
( select STATE, MAX(CNT)
from
( select account_id as ACCOUNT, state as STATE, count(*) as CNT
from DEVICE group by account_id, state ) T2
Group by STATE
);
which is so ugly. 太丑了 Is there a better way to do that ?
有更好的方法吗?
Thanks, 谢谢,
Jack 插口
You can create an intermediate summary table or a view like so: 您可以创建一个中间摘要表或类似的视图:
drop table if exists device_summary;
create table device_summary as
select user_id, state, count(*) as counter
from device
group by user_id, state;
Then, you can run a query like so to get your desired results: 然后,您可以像这样运行查询以获取所需的结果:
select d.*
from device_summary d
inner join (
select state, max(counter) as maxcounter
from device_summary
group by state
) d1 on d.state = d1.state and d.counter = d1.maxcounter;
Example: https://rextester.com/ZMZH93648 范例: https : //rextester.com/ZMZH93648
You can make use of ROW_NUMBER
analytical function as follows: 您可以按以下方式使用
ROW_NUMBER
分析函数:
SELECT
B.USER_ID,
B.STATE,
B.CNT
FROM
(
SELECT
ROW_NUMBER() OVER(
PARTITION BY A.STATE
ORDER BY
A.CNT DESC
) AS RN,
A.USER_ID,
A.STATE,
A.CNT
FROM
(
SELECT
USER_ID,
STATE,
COUNT(1) CNT
FROM
DEVICE
GROUP BY
USER_ID,
STATE
) A
) B
WHERE
B.RN = 1
db<>fiddle demo db <> fiddle演示
Cheers!! 干杯!!
Try this: 尝试这个:
SELECT User_ID, State, count(*) AS Maximum
FROM DEVICE
GROUP BY User_ID, State
ORDER BY User_ID, State
You can use window functions, but only need one level of subquery is needed: 您可以使用窗口函数,但只需要一个子查询级别:
SELECT USER_ID, STATE, CNT
FROM (SELECT USER_ID, STATE, COUNT(*) as CNT,
ROW_NUMBER() OVER (PARTITION BY state ORDER BY COUNT(*) DESC) as seqnum
FROM DEVICE
GROUP BY USER_ID, STATE
) us
WHERE seqnum = 1;
Note: If there are ties, this returns an arbitrary user. 注意:如果有联系,则返回任意用户。 If you want all of them, use
RANK()
instead of ROW_NUMBER()
. 如果要全部使用,请使用
RANK()
而不是ROW_NUMBER()
。
Note: Window functions are only available in MySQL starting with version 8. 注意:窗口功能仅在版本8起的MySQL中可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.