SQLite查询复杂数据

时间:2015-09-04 23:02:20

标签: python sqlite

我做了一些实验,我在多个烧瓶中种植酵母菌株,并从不同的化学品中获取样品。

我已经设置了一个包含StrainId,FlaskNum,DateTime,HarvestIndex,Species,NumLabeledCarbons和MDV字段的SQLite表。

我有兴趣获得最新实验中从每个瓶中收集的最早样品的MDV数据,用于对应于该特定菌株的最新实验中的所有代谢物。

我使用sqlite3包编写了一个Python脚本,使用一系列for循环来检索我需要的数据并且它可以工作,但我怀疑可能有更多以SQL为中心的方法来获取和分组单个数据。

以下是获取代码的基本外观:

import sqlite3 as lite

con = lite.connect('fluxData.db')
with con:
    cur = con.cursor()
    for strainId in cur.execute("SELECT DISTINCT StrainId FROM LCMS WHERE StrainId IN ('U','S','UG','SG');").fetchall():
        for dateVal in cur.execute("SELECT max(date(DateTime)) FROM LCMS WHERE StrainId=?",[strainId[0]]).fetchall():
            for flaskNum in cur.execute("SELECT DISTINCT FlaskNum FROM LCMS WHERE StrainId=? AND date(DateTime)=?",[strainId[0],dateVal[0]]).fetchall():
                for harvestIndex in cur.execute("SELECT min(HarvestIndex) FROM LCMS").fetchall():
                    for species in cur.execute("SELECT DISTINCT Species FROM LCMS WHERE StrainId=? AND date(DateTime)=? AND FlaskNum=? AND HarvestIndex=?",[strainId[0],dateVal[0],flaskNum[0],harvestIndex[0]]).fetchall():
                        print '\n'
                        for row in cur.execute("SELECT NumLabeledCarbons,MDV FROM LCMS WHERE StrainId=? AND date(DateTime)=? AND FlaskNum=? AND HarvestIndex=? AND Species=? ORDER BY NumLabeledCarbons",[strainId[0],dateVal[0],flaskNum[0],harvestIndex[0],species[0]]).fetchall():
                            print row

获得数据后,我将相同物种的数据分组,然后在每组中使用相同的菌株对它们进行平均。

我想知道这是否是最佳方法?有没有办法只使用SQL语句获取所有分组数据?

3 个答案:

答案 0 :(得分:0)

考虑以下SQL聚合查询:

import sqlite3 as lite
con = lite.connect('fluxData.db')

sql = "SELECT StrainId, FlaskNum, Species, NumLabeledCarbons, MDV, \
       Max(date(DateTime)) As LatestExperimentDate, Min(HarvestIndex) As EarliestHarvest \
       FROM LCMS \
       WHERE StrainId IN ('U','S','UG','SG') \
       GROUP BY StrainId, FlaskNum, Species, NumLabeledCarbons, MDV \
       HAVING DateTime = Max(date(DateTime)) AND HarvestIndex = Min(HarvestIndex) \
       ORDER BY  NumLabeledCarbons;"

with con:
   cur = con.cursor()
   cur.execute(sql)   

   for data in cur.fetchall():
      ...

然后,您可以将Avg()Sum()Count()添加到SELECT行中的任何数字列,以便按组计算。

答案 1 :(得分:0)

显然,大多数这些查询的目的只是将结果排序为组。这可以通过ORDER BY完成。

获取每个菌株的最新日期可以使用correlated subquery

完成
SELECT NumLabeledCarbons, MDV
FROM LCMS
WHERE StrainId IN ('U','S','UG','SG')
  AND date(DateTime) = (SELECT max(date(DateTime))
                        FROM LCMS AS L2
                        WHERE L2.StrainId = LCMS.StrainId)
  AND HarvestIndex = (SELECT min(HarvestIndex)
                      FROM LCMS)
ORDER BY StrainId, FlaskNum, Species;

但是,这会重新执行表中每行的子查询。 在单独的子查询中计算四个菌株中每个菌株的最新日期可能更有效,并将其连接回原始表:

SELECT NumLabeledCarbons, MDV
FROM LCMS
JOIN (SELECT StrainId,
             max(DateTime) AS MaxDate
      FROM LCMS
      WHERE StrainId IN ('U','S','UG','SG')
      GROUP BY StrainId) AS MD
ON LCMS.StrainId       = MD.StrainId AND
   date(LCMS.DateTime) = MD.MaxDate
WHERE HarvestIndex = (SELECT min(HarvestIndex)
                      FROM LCMS)
ORDER BY StrainId, FlaskNum, Species;

答案 2 :(得分:0)

方法A是Parfa的答案,我已对其进行了一些修改以使其发挥作用:

db.content.find({'meta.name': 'alpha'})

方法B是CL,我只是因为列名称错误含糊而略微修改:

Find me the document where 'meta.name' !== 'beta'.

方法C是上面的for-loop方法。

我实现并计时每个方法以获取包含我想要的所有数据的中间词典,并验证它们都是相同的。

此外,在100次迭代中以秒为单位计时,发现方法A,B和C的平均值分别为0.05831611,0.05774071和0.23839145秒,各自的标准差为0.0071795,0.00439557和0.01499475。

for-loop方法比CL和Parfait提出的方法长约4倍。

从技术上讲,我希望有一种方法可以将sqlite3返回的数据分为NumLabeledCarbons,每个样本/物种组合的MDV数据以及按物种分组的数据,而不是有序的元组列表。与查询匹配的每一行。虽然我被告知这不是SQL的重点。

然而,这比我提出的解决方案要好得多,并且在尝试理解你的答案时我学到了很多东西。

感谢您抽出宝贵时间回答我的第一个Stack Overflow问题!