首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >初学者SQL问题:在Stack Exchange数据资源管理器中查询金银标记徽章

初学者SQL问题:在Stack Exchange数据资源管理器中查询金银标记徽章
EN

Stack Overflow用户
提问于 2010-06-06 18:42:07
回答 2查看 397关注 0票数 3

我正在使用堆栈交换数据资源管理器来学习SQL,但我认为这个问题的基本原理适用于其他数据库。

我正在查询Badges表,根据Stexdex (从现在起我将这样称呼它),它有以下模式:

  • 徽章
    • Id
    • UserId
    • 名字
    • 日期

这对于像[Epic][Legendary]这样有着独特名字的徽章很有效,但是银和金标记特有的徽章似乎是通过相同的确切名称混合在一起的。

下面是我为[mysql]标记编写的一个示例查询:

代码语言:javascript
复制
SELECT
  UserId as [User Link],
  Date
FROM
  Badges
Where
  Name = 'mysql'
Order By
  Date ASC

(略带注释的)输出是:如stexdex所见

代码语言:javascript
复制
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 

这与目前的银牌黄金收入者名单是一致的,但以更永恒的方式来说,截至2010年5月底,只有2名用户获得了[mysql]的黄金标签: Quassnoi和Bill。从以上结果可以看出,他们的名字是唯一出现两次的。

所以我就是这么理解的:

  • Id第一次出现(按时间顺序排列)是为了银徽章。
  • 第二次是为了金牌

现在,上述结果将银和金项目混合在一起。我的问题是:

  • 这是一个典型的设计,还是有更友好的模式/规范化/不管你怎么称呼它?
  • 在目前的设计中,您如何分别查询银牌和金章?
    • GROUP BY Id并以某种方式选择Date的最小/最大值或第一个/秒?
    • 您如何编写一个查询,先列出所有的银徽章,然后再列出所有的金徽章?
      • 还可以想象一下,“真正的”查询可能更复杂,即不仅仅是按日期列出。
      • 你如何写它,使它不会有太多的重复之间的银和黄金子查询?

代码语言:javascript
复制
- Is it perhaps more typical to do two totally separate queries instead?
- What is this idiom called? A row "partitioning" query to put them into "buckets" or something?

需求澄清

最初,我希望得到以下输出,本质上是:

代码语言:javascript
复制
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     // :

但是到目前为止,用一个单独的栏目来解释银和金也是很棒的,所以也可以自由地去追求这个角度。不过,我还是很好奇你会怎么做。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-06-06 18:59:21

这是一个典型的设计,还是有更友好的模式/规范化/不管你怎么称呼它?

当然,您可以添加类型代码以使其更加显式。但是,当你认为一个人不能在银牌之前得到一枚金徽章,那么日期戳就有了很大的区别。

在目前的设计中,您如何分别查询银牌和金章?按Id分组,以某种方式选择最小/最大值或第一个/秒?

是的-加入到派生表(AKA内联视图),这是一个用户列表&最低日期将返回银徽章。使用HAVING COUNT(*) >= 1也是可行的。您必须使用GROUP BY和COUNT(*) =2‘的组合才能获得金徽章--最大值日期并不能确保用户’d有多个记录.

您如何编写一个查询,先列出所有的银徽章,然后再列出所有的金徽章?

不好意思-被用户,还是所有银牌第一次,然后金牌?前者可以简单地通过使用ORDER BY t.userid, t.date来完成;后者我可能使用分析函数(IE: ROW_NUMBER(),秩()).

是否更典型的做法是执行两个完全独立的查询呢?

看看上面你的要求有多模糊,对我来说.

这个成语叫什么?行“分区”查询将它们放入“桶”或其他什么?

你要问的是以下同义词:分析,窗口,排名.

票数 4
EN

Stack Overflow用户

发布于 2010-06-06 19:05:31

你会做这样的事情,只依赖于日期或总数中的计数。

可以说,查询后面跟着黄金的白银也是没有意义的,而是像这样并行地获取数据:

不幸的是,您还没有真正指定您想要的内容,但是聚合的一个很好的起点是用简单的英语表示它。

例如:“给我标签mysql每个用户的银和金徽章奖励日期”。这确实是:

代码语言:javascript
复制
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:它是两个单独的记录集。分离器是禁止的。作为一种基于setb的操作,不存在“自然”顺序,因此引入了一种:

代码语言:javascript
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2985415

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档