【问题标题】:MySQL >, <, and missing by groupMySQL >、< 和按组缺失
【发布时间】:2012-03-06 05:22:01
【问题描述】:

我在 MySQL 中有两个表,我将它们与以下属性进行比较:

tbl_fac : facility_id, chemical_id, criteria
             10      , 25         , 50
             10      , 26         , 60
             10      , 27         , 60
             11      , 25         , 30
             11      , 27         , 31 
              etc...

tbl_samp: sample_id, chemical_id, result
            5     ,    25         , 51
            5     ,    26         , 61
            6     ,    25         , 51
            6     ,    26         , 61
            6     ,    27         , 500

              etc.... 

这些表是由chemical_id(多对多----呃)连接的,有几千个facility_id,每个facility_id 有几百个chemic_id。还有几千个sample_id,每个sample_id 都有几百个chemic_id。总而言之,tbl_fac 中有大约 500,000 条记录,tbl_samp 中有 1,000,000 多条记录。

我正在尝试从该数据集中提取三组 sample_id:

第 1 组:任何 sample_id,其中 tbl_samp.result > tbl_fac.criteria(即结果超出标准)

第 2 组:tbl_samp.result

第 3 组:tbl_samp.result

问题来了:如何在一个查询中有效地获取所有三个组?

我试过了:

select * 
from tbl_fac 
left join tbl_samp 
    on tbl_fac.chemical_id = tbl_samp.chemical_id

但这只会产生整个数据集(而不是单个样本)缺失的值。我有一个 hackish 查询,它使用第三个表来连接 tbl_fac 和 tbl_samp,但它太丑了,我实际上很尴尬地发布它......

与往常一样,非常感谢您对此的想法!

干杯,

乔什

编辑:理想情况下,我希望返回 sample_id 和 Group - 每个样本 ID 只有一个 Group(我对数据的了解表明它们将始终属于上述三个类别之一)。

【问题讨论】:

  • 您想退回什么?带有sample_id 和某种group_it_belongs_to 列的表?
  • 是的——完全正确。刚刚更新它以反映您的评论。谢谢!

标签: mysql group-by missing-data


【解决方案1】:

此答案假设tbl_fac 中的facility_idchemical_id 存在唯一约束,tbl_sampsample_idchemical_id 存在唯一约束。我所做的是一次一步地建立查询。这是否有效还有待观察。

第 1 组:任何 sample_id,其中 tbl_samp.result > tbl_fac.criteria(即结果超出标准)

SELECT tbl_samp.sample_id,
       'ResultsGreaterThanCriteria' AS samplegroup
FROM   tbl_fac
       INNER JOIN tbl_samp
         ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE  tbl_samp.result > tbl_fac.criteria
GROUP  BY tbl_samp.sample_id

第 2 组:tbl_samp.result

SELECT tbl_samp.sample_id,
       'ResultLessThanCriteriaAndAllChems' AS samplegroup
FROM   tbl_fac
       INNER JOIN tbl_samp
         ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE  tbl_samp.result < tbl_fac.criteria
       AND NOT EXISTS (SELECT *
                       FROM   tbl_fac tf
                              LEFT JOIN tbl_samp ts
                                ON tf.chemical_id = ts.chemical_id
                       WHERE  ts.chemical_id IS NULL
                              AND tbl_samp.sample_id = ts.sample_id)
GROUP  BY tbl_samp.sample_id

第 3 组:tbl_samp.result

SELECT tbl_samp.sample_id,
       'ResultsLessThanCriteriaWithMissingChems' AS samplegroup
FROM   tbl_fac
       INNER JOIN tbl_samp
         ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE  tbl_samp.result < tbl_fac.criteria
       AND EXISTS (SELECT *
                   FROM   tbl_fac tf
                          LEFT JOIN tbl_samp ts
                            ON tf.chemical_id = ts.chemical_id
                   WHERE  ts.chemical_id IS NULL
                          AND tbl_samp.sample_id = ts.sample_id)
GROUP  BY tbl_samp.sample_id 

最后,将所有三个查询合并在一起,得到:

SELECT tbl_samp.sample_id,
       'ResultsGreaterThanCriteria' AS samplegroup
FROM   tbl_fac
       INNER JOIN tbl_samp
         ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE  tbl_samp.result > tbl_fac.criteria
GROUP  BY tbl_samp.sample_id
UNION ALL
SELECT tbl_samp.sample_id,
       'ResultLessThanCriteriaAndAllChems' AS samplegroup
FROM   tbl_fac
       INNER JOIN tbl_samp
         ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE  tbl_samp.result < tbl_fac.criteria
       AND NOT EXISTS (SELECT *
                       FROM   tbl_fac tf
                              LEFT JOIN tbl_samp ts
                                ON tf.chemical_id = ts.chemical_id
                       WHERE  ts.chemical_id IS NULL
                              AND tbl_samp.sample_id = ts.sample_id)
GROUP  BY tbl_samp.sample_id
UNION ALL
SELECT tbl_samp.sample_id,
       'ResultsLessThanCriteriaWithMissingChems' AS samplegroup
FROM   tbl_fac
       INNER JOIN tbl_samp
         ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE  tbl_samp.result < tbl_fac.criteria
       AND EXISTS (SELECT *
                   FROM   tbl_fac tf
                          LEFT JOIN tbl_samp ts
                            ON tf.chemical_id = ts.chemical_id
                   WHERE  ts.chemical_id IS NULL
                          AND tbl_samp.sample_id = ts.sample_id)
GROUP  BY tbl_samp.sample_id 

【讨论】:

  • 可能有几个实例,其中给定的 facility_id 或 sample_id 有重复的 chemical_id - 但我知道你打算用这个去哪里......现在看看。感谢您的输入!看起来很棒!
  • 这非常非常接近。据我所知,“ResultLessThanCriteriaAndAllChems”组首先通过化学 ID 链接 tbl_fac 和 tbl_samp 并确认结果
  • 我似乎从未得到任何“ResultLessThanCriteriaAndAllChems”结果。有什么想法吗?
  • 说实话,你的数据模型让我有点困惑:-/ 所以我将子查询加入了错误的字段。通常,M:M 关系有一个联结表。只有 2 张桌子,我有一半希望在某处有 1:M 或 1:1 的关系。这些表的主键是什么?是的,嵌套查询的想法是查看样本中是否缺少(当前)结果低于标准的化学物质。我编辑了 SQL 以通过 sample_id 将子查询链接回主查询。
  • 这实际上现在可以正常工作了。这里没有 1:1 的关系(我以为我提到这是多对多的 - 这很烦人,但我无法控制它),但根据你的工作,我能够采取巨大的飞跃并让它发挥作用。非常感谢!
【解决方案2】:
SELECT
    sample_id,
    IF(result = criteria, -1,  /* unspecified behavior */
     IF(result > criteria, 1,
      IF(nb_chemicals = total_nb_chemicals, 2, 3))) AS grp

FROM (
    SELECT s.result, s.sample_id, f.criteria, f.chemical_id,
        COUNT(DISTINCT f.chemical_id) AS nb_chemicals
    FROM tbl_fac f JOIN tbl_samp s
        ON f.chemical_id = s.chemical_id
    GROUP BY s.sample_id
) t 

CROSS JOIN (
    SELECT COUNT(DISTINCT chemical_id) AS total_nb_chemicals
    FROM tbl_fac
) u

新解决方案:

SELECT
    s.sample_id,
    IF(s.result = f.criteria, -1,  /* unspecified behavior */
     IF(s.result > f.criteria, 1,
      IF(sample_nb_chemicals = total_nb_chemicals, 2, 3))) AS grp

FROM
    tbl_fac f JOIN tbl_samp s
    ON f.chemical_id = s.chemical_id

    JOIN (
        SELECT s.sample_id, 
               COUNT(DISTINCT f.chemical_id) AS sample_nb_chemicals
        FROM tbl_fac f JOIN tbl_samp s
             ON f.chemical_id = s.chemical_id
        GROUP BY s.sample_id
    ) u
       ON s.sample_id = u.sample_id

    CROSS JOIN (
        SELECT COUNT(DISTINCT chemical_id) AS total_nb_chemicals
        FROM tbl_fac
    ) v

GROUP BY sample_id, grp

【讨论】:

  • 感谢您的回复!现在正在经历。
  • 我认为您在此查询中心的嵌套查询只为每个 sample_id 返回一个结果。实际上,我需要将每个结果与每个标准进行比较,以检查对于给定的 sample_id,sample_id 是否具有 Group_1、Group_2 或 Group_3 属性。也就是说 - 您的查询非常快,但它只分析从嵌套查询组函数返回的第一个结果(无论可能是什么)。这正是我试图解决这个问题时遇到的问题!有什么想法吗?
  • 是的,你是对的。我认为您的三组 sample_id 已知是互斥的,这意味着您只需要查看每个 sample_id 的一个化学/结果/标准组合。如果不是这样,我会考虑如何让它发挥作用。
  • (顺便说一下,我已修复它以反映这一点。)
  • Mike - 结果证明这是一个不错的选择。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-12-12
  • 2017-12-12
  • 2019-04-11
  • 2020-06-19
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
相关资源
最近更新 更多