我有一个包含三个字段Id,Player,ColorNumber的SQL表。 Id不是主键,可以重复。表格如下:
我想用它来创建一个Captains表,例如。但是对于给定的Id,应该根据玩家的最大出现次数选择队长。
例如。对于123,迈克发生最多,船长应该是迈克。 对于345,没有明显的多数,所以将队长字段留空 对于567,它将是Schuyler,尽管太空和Schuyler有相同的数量。 898是玛丽。请注意,Mike也出现在898密钥中。
这是我的输出。
到目前为止,我写道:
SELECT COUNT(*) as counts,[Class ID],Player
FROM [Test].[dbo].[Players]
GROUP BY [Class ID],Player
给了我一个结果:
我猜测存储过程是编写此方法的最佳方法,并使新表与新的直接查询相对。由于我需要处理如果有相同名称的情况,那么船长将是空白的。但是,我对存储过程相当新,并且不确定如何去处理它并重新使用上面查询中的信息来执行此操作并处理这些情况。我想有一个CASE ..当我在程序中查看操作但我不确定如何使用它。
如果你有其他选择而不是程序,请建议。任何帮助将不胜感激。
答案 0 :(得分:1)
这称为"模式"在统计中。您可以使用窗口功能轻松完成此操作:
SELECT [Class ID],
COALESCE(MAX(CASE WHEN seqnum = 1 THEN PLAYER END), MAX(CASE WHEN seqnum = 2 THEN PLAYER END)
) as captain
FROM (SELECT COUNT(*) as counts, [Class ID], Player,
ROW_NUMBER() OVER (PARTITION BY [Class ID] ORDER BY COUNT(*) DESC) as seqnum
FROM [Test].[dbo].[Players] p
GROUP BY [Class ID], Player
) p
GROUP BY [Class ID];
注意:需要COALESCE()
,因为您有很多空白值。我怀疑你不想要他们为船长。
编辑:
如果在有关系时你不想要的话:
SELECT [Class ID],
(CASE WHEN MAX(CASE WHEN seqnum = 1 AND cnt = 1 AND player IS NOT NULL THEN 1 ELSE 0 END) = 1
THEN PLAYER
WHEN MAX(CASE WHEN seqnum = 1 AND cnt > 1 THEN 1 ELSE 0 END) > 0
THEN NULL
WHEN MAX(CASE WHEN seqnum = 2 AND cnt = 1
THEN PLAYER
END) as captain
FROM (SELECT p.*, COUNT(*) OVER (PARTITION BY [Class ID], seqnum) as cnt
FROM (SELECT COUNT(*) as counts, [Class ID], Player,
DENSE_RANK() OVER (PARTITION BY [Class ID] ORDER BY COUNT(*) DESC) as seqnum
FROM [Test].[dbo].[Players] p
GROUP BY [Class ID], Player
) p
) p
GROUP BY [Class ID];