通过另一列SQL中的唯一条目对列进行分组

时间:2019-08-26 00:54:01

标签: sql azure-sql-database

我有以下数据集

enter image description here

我想查询数据以生成每个用户名的唯一主机名列表,其中还包括该记录的最后登录时间。例如,产生以下数据集。

enter image description here

目标是检测用户帐户共享以及主机名异常多的用户。

我知道足够多的SQL会给自己带来麻烦,但是我只是写的查询不够频繁,以至于不能熟练地编写此查询而不会花半天时间。有人可以协助吗?

我们正在使用Azure SQL(SQL Server),但是我可以翻译另一种SQL语言的答案。

谢谢

更新

我使用了以下

select username, hostname, max(logintimeutc)
from loginrecords
group by username, hostname

这将返回一个好的数据集,但是当我尝试以下操作时,尽管上面的查询显示了针对同一主机名的多个用户名,但它仍返回0条记录

select username, hostname, max(logintimeutc)
from loginrecords
group by username, hostname
having count(distinct(hostname)) > 1

4 个答案:

答案 0 :(得分:0)

  

我想查询数据以生成每个用户名的唯一主机名列表,其中还包括该记录的最后登录时间。

我认为您只想要group by

select username, hostname, max(logintimeutc)
from t
group by username, hostname;

答案 1 :(得分:0)

您可以为此使用row_number()。

select * from table1 t1
inner join
    (select row_number() over (partition by HostName, UserName order by LoginTimeUTC desc) as rn, UserName
            ,LoginTimeUTC, HostName from table1) as t2
on t2.UserName = t1.UserName and t2.LoginTimeUTC = t2.LoginTimeUTC and t2.HostName = t1.HostName
where t2.rn = 1

答案 2 :(得分:0)

如果我理解正确,不考虑登录时间就可以得到2个结果,请尝试以下查询:

select username,hostname,
count(*) over (partition by hostname) as NUMBER_OF_USERS_FOR_THIS_HOST,
count(*) over (partition by username) as NUMBER_OF_HOSTS_FOR_THIS_USER
from loginrecords
group by username, hostname;

答案 3 :(得分:0)

首先,我使用以下查询创建了一个测试环境。如果您自己在以后的问题中提供这些(或文本表格数据),那将是很好的。带有数据的屏幕截图对于测试目的非常不友好。

CREATE TABLE [LoginRecords] (
    [LoginTimeUTC] SMALLDATETIME,
    [UserName] VARCHAR(5),
    [HostName] VARCHAR(5)
);
GO

INSERT INTO [LoginRecords] VALUES
    ('2019-08-22T09:51:00', 'user1', 'host1'),
    ('2019-08-25T09:31:00', 'user1', 'host2'),
    ('2019-08-30T10:51:00', 'user1', 'host2'),
    ('2019-08-25T09:51:00', 'user2', 'host2'),
    ('2019-08-25T05:51:00', 'user2', 'host3'),
    ('2019-08-30T09:51:00', 'user2', 'host3'),
    ('2019-08-25T09:31:00', 'user3', 'host4'),
    ('2019-08-30T10:51:00', 'user3', 'host4'),
    ('2019-08-25T09:51:00', 'user3', 'host4'),
    ('2019-08-25T05:51:00', 'user3', 'host5'),
    ('2019-08-25T09:51:00', 'user4', 'host6'),
    ('2019-08-25T09:31:00', 'user4', 'host6'),
    ('2019-08-30T10:51:00', 'user4', 'host6'),
    ('2019-08-25T09:51:00', 'user4', 'host7'),
    ('2019-08-30T05:51:00', 'user4', 'host7');
GO

SELECT [LoginTimeUTC], [UserName], [HostName]
FROM [LoginRecords];

现在就解决您的实际问题。我正在考虑您的最后一个查询,该查询没有返回您想要的结果:

select username, hostname, max(logintimeutc)
from loginrecords
group by username, hostname
having count(distinct(hostname)) > 1

代替HAVING子句,您可以添加WHERE子句以仅过滤与多个主机名一起使用的用户名。

select username, hostname, max(logintimeutc)
from loginrecords
where username in (select username
                   from loginrecords
                   group by username
                   having count(distinct hostname) > 1)
group by username, hostname

这将产生以下结果:

username      hostname      (No column name)
user1         host1         22/08/2019 9:51
user1         host2         30/08/2019 10:51
user2         host2         25/08/2019 9:51
user2         host3         30/08/2019 9:51
user3         host4         30/08/2019 10:51
user3         host5         25/08/2019 5:51
user4         host6         30/08/2019 10:51
user4         host7         30/08/2019 5:51