假设我有一个带有以下字段的mySQL表(用户):

userid
gender
region
age
ethnicity
income

我希望能够根据用户输入的数目返回总记录数。此外,他们还将提供其他标准。

在最简单的示例中,他们可能要求提供1000条记录,其中600条记录的性别应为“男”,而400条记录的性别应为“女”。这很简单。

现在,再往前走一步。假设他们现在要指定Region:
GENDER
    Male:   600 records
    Female: 400 records

REGION
    North:  100 records
    South:  200 records
    East:   300 records
    West:   400 records

同样,只应返回1000条记录,但最后必须有600位男性,400位女性,100位北方人,200位南方人,300位东方人和400位西方人。

我知道这不是有效的语法,但是使用伪mySQL代码,它有望说明我正在尝试执行的操作:
(SELECT * FROM users WHERE gender = 'Male' LIMIT 600
UNION
SELECT * FROM users WHERE gender = 'Female' LIMIT 400)

INTERSECT

(SELECT * FROM users WHERE region = 'North' LIMIT 100
UNION
SELECT * FROM users WHERE region = 'South' LIMIT 200
UNION
SELECT * FROM users WHERE region = 'East' LIMIT 300
UNION
SELECT * FROM users WHERE region = 'West' LIMIT 400)

请注意,我不是在寻找一次性查询。记录的总数和每个条件内的记录数将根据用户的输入不断变化。因此,我正在尝试提出一种可以反复使用的通用解决方案,而不是硬编码的解决方案。

为了使事情变得更复杂,现在添加更多条件。每个组也可能有年龄,种族和收入,并有各自固定的记录数量,上面附加了其他代码:
INTERSECT

(SELECT * FROM users WHERE age >= 18 and age <= 24 LIMIT 300
UNION
SELECT * FROM users WHERE age >= 25 and age <= 36 LIMIT 200
UNION
SELECT * FROM users WHERE age >= 37 and age <= 54 LIMIT 200
UNION
SELECT * FROM users WHERE age >= 55 LIMIT 300)

INTERSECT

etc.

我不确定这是否可以在一个查询中编写,或者是否需要多个语句和迭代。

最佳答案

展平您的标准

您可以将多维标准简化为单级标准

现在,可以通过以下一个查询来实现此标准

(SELECT * FROM users WHERE gender = 'Male' AND region = 'North' LIMIT 40) UNION ALL
(SELECT * FROM users WHERE gender = 'Male' AND region = 'South' LIMIT 80) UNION ALL
(SELECT * FROM users WHERE gender = 'Male' AND region = 'East' LIMIT 120) UNION ALL
(SELECT * FROM users WHERE gender = 'Male' AND region = 'West' LIMIT 160) UNION ALL
(SELECT * FROM users WHERE gender = 'Female' AND region = 'North' LIMIT 60) UNION ALL
(SELECT * FROM users WHERE gender = 'Female' AND region = 'South' LIMIT 120) UNION ALL
(SELECT * FROM users WHERE gender = 'Female' AND region = 'East' LIMIT 180) UNION ALL
(SELECT * FROM users WHERE gender = 'Female' AND region = 'West' LIMIT 240)

问题
  • 它并不总是返回正确的结果。例如,如果来自北方的男性用户少于40个,则查询将返回少于1,000条记录。


  • 调整条件

    假设来自北方的男性用户少于40个。然后,您需要调整其他标准数量,以弥补“男性”和“北部”缺少的数量。我相信使用裸露的SQL不可能做到这一点。我想到的是伪代码。为了简化起见,我认为我们只会查询男性,女性,北方和南方
    conditions.add({ gender: 'Male',   region: 'North', limit: 40  })
    conditions.add({ gender: 'Male',   region: 'South', limit: 80  })
    conditions.add({ gender: 'Female', region: 'North', limit: 60  })
    conditions.add({ gender: 'Female', region: 'South', limit: 120  })
    
    foreach(conditions as condition) {
        temp = getResultFromDatabaseByCondition(condition)
        conditions.remove(condition)
    
        // there is not enough result for this condition,
        // increase other condition quantity
        if (temp.length < condition.limit) {
            adjust(...);
        }
    }
    

    假设只有30个北风公。因此,我们需要调整+10男性,和+10北方人。
    To Adjust
    ---------------------------------------------------
    Male        +10
    North       +10
    
    Remain Conditions
    ----------------------------------------------------
    { gender: 'Male',   region: 'South', limit: 80 }
    { gender: 'Female', region: 'North', limit: 60  }
    { gender: 'Female', region: 'South', limit: 120  }
    

    “男性” +“南部”是与“男性”调整条件匹配的第一个条件。将其增加+10,并将其从“剩余条件”列表中删除。由于我们增加了南方,因此我们需要在其他情况下将其减少。因此,将“南方”条件添加到“调整”列表中
    To Adjust
    ---------------------------------------------------
    South       -10
    North       +10
    
    Remain Conditions
    ----------------------------------------------------
    { gender: 'Female', region: 'North', limit: 60  }
    { gender: 'Female', region: 'South', limit: 120  }
    
    Final Conditions
    ----------------------------------------------------
    { gender: 'Male',   region: 'South', limit: 90 }
    

    查找与“南部”匹配的条件,然后重复相同的过程。
    To Adjust
    ---------------------------------------------------
    Female      +10
    North       +10
    
    Remain Conditions
    ----------------------------------------------------
    { gender: 'Female', region: 'North', limit: 60  }
    
    Final Conditions
    ----------------------------------------------------
    { gender: 'Female', region: 'South', limit: 110  }
    { gender: 'Male',   region: 'South', limit: 90 }
    

    最后
    { gender: 'Female', region: 'North', limit: 70  }
    { gender: 'Female', region: 'South', limit: 110  }
    { gender: 'Male',   region: 'South', limit: 90 }
    

    我还没有想出调整的确切实现方式。这比我预期的要难。一旦我弄清楚如何实现它,我将进行更新。

    关于mysql - MySQL查询可获取众多带有限制的查询的 “intersection”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27160122/

    10-11 03:31
    查看更多