我做了一些实验,我在多个烧瓶中种植酵母菌株,并从不同的化学品中获取样品。
我已经设置了一个包含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语句获取所有分组数据?
答案 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问题!