【问题标题】:Select every other row as male/female from mysql table从mysql表中选择每隔一行作为男性/女性
【发布时间】:2012-04-15 12:03:53
【问题描述】:

我有一个表格,其中包含性别编码为 0 和 1 的人员。我需要每隔一行选择男性/女性。我以为我可以通过使用模数和性别代码 0 和 1 以某种方式管理这个问题,但我还没有设法弄清楚......

我正在寻找的结果如下所示:

+-----+--------+--------+ |行 |性别 |姓名 | +-----+--------+--------+ | 1 |女|丽莎 | | 2 |男|格雷格 | | 3 |女|玛丽 | | 4 |男|约翰 | | 5 |女|珍妮 | +-----+--------+--------+

等等

另一种方法是在 PHP 中合并 2 个单独的数组,但我真的很喜欢它作为 SQL 查询...

欢迎提出任何建议!

【问题讨论】:

  • 我不确定我是否明白您的问题,您是否想从您的数据库中仅检索男性(或女性)?目前尚不清楚您要完成什么。
  • 请说明您要求的结果..
  • 我需要每隔一行检索一次男性/女性:例如1. 丽莎,2. 格雷格,3. 玛丽,4. 约翰,5. 珍妮
  • 您的逻辑似乎有缺陷,因为无法保证男女人数相等。您认为应该如何处理?
  • 如果这是您需要的结果,您选择的表格是什么样的?

标签: mysql sql select modulo


【解决方案1】:

执行两个子查询来选择男性和女性。使用排名函数来枚举它们。

Males:
1 | Peter
2 | John
3 | Chris

Females:
1 | Marry
2 | Christina
3 | Kate

然后按 x10 进行多人游戏排名结果,女性加 5。所以你有这个:

Males:
10 | Peter
20 | John
30 | Chris

Females:
15 | Marry
25 | Christina
35 | Kate

然后执行 UNION ALL 并按新排序顺序/新 ID 排序。

合起来应该是这样的(伪代码)

SELECT
Name
FROM
(subquery for Males: RANK() AS sortOrd, Name)
UNION ALL
(subquery for Females: RANK()+1 AS SortOrd, Name)
ORDER BY SortOrd

结果应该是这样的:

Males and Females:
10 | Peter
15 | Marry
20 | John
25 | Christina
30 | Chris
35 | Kate  

【讨论】:

  • 对不起,我没有注意到这是 MySQL 相关的问题。不确定MySQL是否有排名功能。
  • 它没有,但你可以使用用户变量来实现。
【解决方案2】:

找到Emulate Row_Number() 并针对您的情况进行了一些修改。

set @rownum := 0;
set @pg := -1;

select p.name, 
       p.gender
from
  (
    select name,
           gender,
           @rownum := if(@pg = gender, @rownum+1, 1) as rn, 
           @pg := gender as pg 
    from persons
    order by gender
  ) as p
order by p.rn, p.gender

试试SQL Fiddle

注意:来自9.4. User-Defined Variables

作为一般规则,您永远不应该为用户变量赋值 并读取同一语句中的值。你可能会得到 您期望的结果,但这不能保证。

我会让你决定是否可以使用它。我不使用 MySQL,所以我不能告诉你是否应该担心。

【讨论】:

  • 我们越来越近了,但还没有到。你的代码只能部分工作,因为这些行似乎给出了相同数量的性别,但并不像其他每一行一样严格。这只会在更多行时变得明显:sqlfiddle.com/#!2/05b02/1
  • @darwin 看起来像派生表中的 order by gender 处理了这个问题。
【解决方案3】:

类似于 Mikael 的解决方案,但无需多次排序结果集 -

SELECT *
FROM (
    SELECT people.*,
        IF(gender=0, @mr:=@mr+1, @fr:=@fr+1) AS rank
    FROM people, (SELECT @mr:=0, @fr:=0) initvars
) tmp
ORDER BY rank ASC, gender ASC;

为了避免必须同时订购内部和外部选择,我在内部选择中使用了单独的计数器(@mr - 男性排名,@fr - 女性排名)。

【讨论】:

    【解决方案4】:

    我有一个表格,其中包含性别编码为 0 和 1 的人员

    那你为什么要假设结果集中的行顺序呢?在我看来,将 0/1 转换为“男性”/“女性”要强大得多:

    select name, case gender when 0 then 'male' else 'female' end
    from Person
    

    【讨论】:

    • 我使用 0 和 1 的原因是因为我认为使用模 2 可以达到我想要的效果
    【解决方案5】:
    SELECT alias.*, ROW_NUMBER() OVER (PARTITION BY GENDER ORDER BY GENDER) rnk
    FROM TABLE_NAME
    ORDER BY rnk, GENDER DESC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-05
      • 1970-01-01
      • 2016-09-02
      • 2020-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多