【问题标题】:SQL Sampling based on the whole population基于总体的 SQL 抽样
【发布时间】:2017-06-05 15:54:26
【问题描述】:

我有很多记录...假设有 10,000 名运动员,按运动分组,其中(下面的数字是可变的):

4,000 are from NBA
2,000 are from NHL
3,000 are from MLB 
1,000 are from NFL

我如何构建一个示例查询,该查询将根据总体对 100 条记录进行抽样,而不是完全随机,而是抽出:

NBA/总人口=X Select Top X * From MainTable Where League='NBA'(类似这样)

40 个名字来自 NBA 20 个名字来自 NHL 30 个名字来自 MLB 10 个名字来自 NFL。

这只是一个总体样本,这里的逻辑是计算相对于整个总体的比率,然后将它们应用于样本量。

问候

【问题讨论】:

标签: sql ms-access


【解决方案1】:

考虑对排名顺序使用计数相关子查询,然后将其用作采样率的过滤条件。

SELECT main.*
FROM 
   (SELECT *,
         (SELECT Count(*) FROM MainTable sub 
          WHERE sub.League = t.League AND sub.UniqueID <= t.UniqueID) As Rank
    FROM MainTable t) AS main

WHERE main.Rank <= CInt((SELECT Count(*) FROM MainTable sub
                         WHERE sub.League = main.League) / 
                         (SELECT Count(*) FROM MainTable) * 100)
ORDER BY main.League, main.Rank

用嵌套子查询和派生表解释上述查询:

  1. 派生表 main 是精确的源 MainTable,带有一个名为 Rank 的新列,它给出了记录的序数每个联赛。因此,对于第一个 NBA 记录(不一定是第一行),它被标记为排名 1,下一个 NBA 记录(可能出现在第 89 行等任何地方)被标记为 2,依此类推。是的,如果需要,Rank 会上升到 4,000!

  2. 一旦计算出此 Rank 字段并为每个 League 分组提供序号 1、2、3、... 指标,我们就会将此 SELECT 语句定位为 @ 中的派生表987654323@ 子句,以便在WHERE 过滤器中使用 Rank 作为采样率。我们无法在同一个SELECT 调用中计算列和过滤器。

  3. 样本比率是用于计算商的最后两个子查询:(与当前行匹配的联赛记录数/表记录总数)。然后将该值乘以每个样本配额的 100。 CInt 用于返回可能的十进制比率的整数值。还要考虑Round(..., 0),它舍入而不是去除小数点。

【讨论】:

  • Parfait...有没有办法随机排列排名?似乎它以相同的方式对记录进行排名....如果我想每次运行此查询时都得到不同的结果怎么办?
  • 好问题。考虑提出一个新问题,因为答案可能涉及数据库层之上的应用层代码(VBA、PHP、Python、Java 等)。归根结底,SQL 只是一种特殊用途的声明性语言,其中一旦声明的列/变量是不可变的。
【解决方案2】:
Dim Leagues(1 To 4) As String

Leagues(1) = "NHL"
Leagues(2) = "MLB"
Leagues(3) = "NFL"
Leagues(4) = "MLS"


Set db = CurrentDb

For x = 1 To 4

y = 0
sqql = "Select * from Maintable Where League = '" & leagues(x) & "'"

Set cf = db.OpenRecordset(sqql)

Set samp = db.OpenRecordset("RANDOMSAMPLE")






Do While y < (x * 1000) ' adjust as necessary just swagged in you wanted 1000 from league 1, 2000 league 2 etc

cf.MoveLast
cf.MoveFirst

i = Int((cf.RecordCount - 1 + 1) * Rnd + 1)

cf.Move (i)

With samp

.AddNew

.fields("Yourfield here") = cf![your field ]

' repeat as nec

.Update

End With
y = y + 1
Loop


cf.Close
Next x

samp.Close

【讨论】:

    猜你喜欢
    • 2016-08-28
    • 2020-01-23
    • 1970-01-01
    • 2021-01-02
    • 2017-11-16
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多