0

使用 SQL,我正在尝试对表中的数据进行 3 维分组,为此我需要一种方法来修改基于某些分组标准输出的值。然后我计划使用 GROUP 命令最终将行分组在一起。

用一个例子来描述更容易。

我跑

SELECT b as b_bin
   , l as l_bin
   , k_1AperMag1 as k1_bin
   , count(*) as num
FROM gpssource
WHERE b between -1.1 and 1.1
   and l between 9.9 and 11.6
   and k_1AperMag1 between 0 and 25 
GROUP BY b, l, k_1AperMag1

得到一张桌子

b_bin               | l_bin              | k1_bin      | num
-1.0115976238979311 | 0.968853586216488  | 13.680575   | 1
-1.0299234557450931 | 11.591887279330654 | 16.761375   | 1
-0.3757959886541285 | 11.446711966673629 | 16.372013   | 1
-0.7250531677528679 | 11.357881248039163 | 17.16921    | 1
...and about 100 million more rows

我基本上需要将每一行分成 b_bin、l_bin 和 k1_bin 的组。比如第一行需要进入ab bin -1.1 -> -1.0, l bin 0.9 -> 1.0 and k1 bin 13 -> 14。我在SQL中这样做的想法是把-1.0115976238979311改为-1.05, 0.968853586216488到 0.95 和 13.680575 到 13.5,然后使用 GROUP by 命令将它们实际分组到 bin 中并获取每组 bin 的计数。

我的最终结果将是:

b_bin | l_bin | k1_bin | num
-1.05 |  0.95 |   13.5 |  23
-0.95 |  0.95 |   13.5 |  20
-0.95 |  0.85 |   13.5 |  25
-0.95 |  0.85 |   12.5 |  23
and more, for each bin in b, l and k1.

最终,我将它放入一个矩阵并为它创建一个图像,其中 b 和 l 是 x 和 y 坐标,k1 是 3d 空间中的一个切片,这导致了这样的事情(这是通过在 python 中对数据进行分箱创建的): 银河系密度图

不幸的是,我不确定如何将实际值更改为 bin 的中心值。这甚至可以用 SQL 实现吗?我在 python 中完成了所有这些工作,但出于逻辑原因,我需要使用 SQL 来对数据进行分类。

所以我的基本问题是:如何修改 SELECT 打印出的值。我可以使用 format() 以多种方式对其进行格式化,但据我所知,它不允许我选择自己的值来输出...... SQL 甚至有函数吗?我用谷歌搜索了一段时间,找不到太多关于这件事的...

任何指针将不胜感激!

4

1 回答 1

2

我已经写了一些 SQL 来获得你想要的结果:http ://www.sqlfiddle.com/#!2/1a54a/1

以下是代码。我不确定这会表现如何,但您可以尝试一下:

SET @bbinSize = 0.1;
SET @lbinSize = 0.1;
SET @kbinSize = 1;
SELECT
    bbin,
    lbin,
    kbin,
    COUNT(*)
FROM
(
    SELECT
        a.b,
        a.l,
        a.k_1AperMag1,
        ((FLOOR(((1 / @bbinSize) * a.b)) * @bbinSize) + @bbinSize / 2) bbin,
        ((FLOOR(((1 / @lbinSize) * a.l)) * @lbinSize) + @lbinSize / 2) lbin,
        ((FLOOR(((1 / @kbinSize) * a.k_1AperMag1)) * @kbinSize) + @kbinSize / 2) kbin
    FROM

    MyTable a
    ) bins
GROUP BY 
    bbin,
    lbin,
    kbin

更好的主意是创建三个新表 , ,BBin每个表都包含三列, , 。然后将每个 bin 填充到这些中。LBinKBinNameMinValueMaxValue

您的查询可能会变成这样:

SELECT
    BBin.Name,
    LBin.Name,
    KBin.Name
    COUNT(*) as MyCount
FROM
    MyTable
    LEFT JOIN BBin ON MyTable.B >= BBin.MinValue AND MyTable.B < BBin.MaxValue
    LEFT JOIN LBin ON MyTable.L >= LBin.MinValue AND MyTable.L < LBin.MaxValue
    LEFT JOIN KBin ON MyTable.KAperMag1 >= KBin.MinValue AND MyTable.KAperMag1 < KBin.MaxValue
GROUP BY
    BBin.Name
    LBin.Name
    KBin.Name

我怀疑第二个选项会表现得更好,但我会把它留给你测试。

于 2012-10-23T14:48:40.513 回答