我正在使用Stack Exchange Data Explorer来学习SQL,但我认为问题的基础知识适用于其他数据库。
我正在尝试查询Badges
表,根据Stexdex(我将从现在开始称之为),它具有以下模式:
这适用于具有唯一名称的[Epic]
和[Legendary]
等徽章,但银色和金色标记特定的徽章似乎通过具有相同的名称混合在一起。
以下是我为[mysql]
标记撰写的示例查询:
SELECT
UserId as [User Link],
Date
FROM
Badges
Where
Name = 'mysql'
Order By
Date ASC
(略带注释)输出为:as seen on stexdex:
User Link Date
--------------- ------------------- // all for silver except where noted
Bill Karwin 2009-02-20 11:00:25
Quassnoi 2009-06-01 10:00:16
Greg 2009-10-22 10:00:25
Quassnoi 2009-10-31 10:00:24 // for gold
Bill Karwin 2009-11-23 11:00:30 // for gold
cletus 2010-01-01 11:00:23
OMG Ponies 2010-01-03 11:00:48
Pascal MARTIN 2010-02-17 11:00:29
Mark Byers 2010-04-07 10:00:35
Daniel Vassallo 2010-05-14 10:00:38
这与撰写本文时silver和gold收入者的当前列表一致,但是以更加永恒的方式发言,截至2010年5月底,只有2位用户获得了黄金[mysql]
标签:Quassnoi和Bill Karwin,如上述结果所示,他们的名字是唯一出现两次的名字。
所以这就是我理解的方式:
Id
第一次出现(按时间顺序)是银徽章现在,上述结果将银色和金色条目混合在一起。我的问题是:
GROUP BY Id
并以Date
某种方式选择最小/最大或第一/秒?最初我想要以下输出,主要是:
User Link Date
--------------- -------------------
Bill Karwin 2009-02-20 11:00:25 // result of query for silver
Quassnoi 2009-06-01 10:00:16 // :
Greg 2009-10-22 10:00:25 // :
cletus 2010-01-01 11:00:23 // :
OMG Ponies 2010-01-03 11:00:48 // :
Pascal MARTIN 2010-02-17 11:00:29 // :
Mark Byers 2010-04-07 10:00:35 // :
Daniel Vassallo 2010-05-14 10:00:38 // :
------- maybe some sort of row separator here? can SQL do this? -------
Quassnoi 2009-10-31 10:00:24 // result of query for gold
Bill Karwin 2009-11-23 11:00:30 // :
但到目前为止,单独的银色和金色专栏的答案也很棒,所以也可以自由地追求这个角度。不过,我仍然很好奇你是怎么做的。
答案 0 :(得分:4)
这是一个典型的设计,还是有更友好的架构/规范化/无论你怎么称呼它?
当然,您可以添加类型代码以使其更明确。但是当你认为在银牌之前无法获得金徽章时,日期戳很有意义区分它们。
在目前的设计中,您如何分别查询银色和金色徽章? GROUP BY Id并以某种方式按日期选择最小/最大或第一/秒?
是 - 加入派生表(AKA内联视图),这是一个用户列表&最短的日期将返回银徽章。使用HAVING COUNT(*) >= 1
也可以。您必须使用GROUP BY和HAVING COUNT(*)= 2`的组合来获取金徽章 - 最大日期不能确保用户ID有多个记录...
如何编写一个查询,首先列出所有的银徽章,然后是所有的金徽章?
很抱歉 - 首先是用户,还是所有银牌,然后是金牌?前者可以简单地使用ORDER BY t.userid, t.date
完成;后者我可能会使用分析函数(IE:ROW_NUMBER(),RANK())......
相反,做两个完全独立的查询可能更典型吗?
无论如何,请参阅上文,了解您的要求是多么模糊......
这个成语叫什么?一行“分区”查询将它们放入“桶”或其他东西?
您所询问的内容由以下同义词引用:Analytic,Windowing,ranking ...
答案 1 :(得分:3)
你会做这样的事情,只依赖日期或聚合计数。
可以说,查询白银后跟黄金也没有意义,而是像这样并排获取数据:
不幸的是,你还没有真正指定你想要的东西,但聚合的一个好的起点是用简单的英语表达
示例:“为每个用户提供标签mysql的银色和金色徽章奖励日期”。这是做什么的:
SELECT
UserId as [User Link],
min(Date) as [Silver Date],
case when count(*) = 1 THEN NULL ELSE max(date) END
FROM
Badges
Where
Name = 'mysql'
group by
UserId
Order By
case when count(*) = 1 THEN NULL ELSE max(date) END DESC, min(Date)
更新后编辑:
您想要的输出不是SQL:它是2个独立的记录集。分离器是不行的。作为基于setb的操作,没有“自然”顺序,因此这引入了一个:
SELECT
UserId as [User Link],
min(Date) as [Date],
0 as dummyorder
FROM
Badges
Where
Name = 'mysql'
group by
UserId
union all
select
UserId as [User Link],
max(Date) as [Date],
1 as dummyorder
FROM
Badges
Where
Name = 'mysql'
group by
UserId
having
count(*) = 2
Order By
dummyorder, Date