SQL - 在具有许多条件的每个列之间打印许多单词

时间:2015-07-07 04:40:04

标签: mysql

好的,首先我有不可变的值:

4   8   16   32   64   128   256

我有一张类似的表:

+----+------+---------------------+-------------+
| id |   full_name  |  club_name  |  y_of_birth |
+----+------+---------------------+-------------+
| 1  | Ahmed Sayed  |   El Ahly   |    2000     |
+----+------+---------------------+-------------+
| 2  | Kareem Gaber |   El Ahly   |    2000     |
+----+------+---------------------+-------------+
| 3  | Maher Zein   |   El Ahly   |    2003     |
+----+------+---------------------+-------------+
| 4  | Mohab Saeed  |   El Ahly   |    2003     |
+----+------+---------------------+-------------+
| 5  | Kamal saber  |   wadi dgla |    2000     |
+----+------+---------------------+-------------+
| 6  | gamel kamel  |   el-nasr   |    2002     |
+----+------+---------------------+-------------+
| 7  | omar galal   |   Cocorico  |    2000     |
+----+------+---------------------+-------------+
| 8  | Kamal saber  |   Cocorico  |    2004     |
+----+------+---------------------+-------------+
| 9  | Mohamed gad  |   Ismaily   |    2000     |  
+----+------+---------------------+-------------+
| 10 | ehab zeyad   |   Ismaily   |    2005     |
+----+------+---------------------+-------------+
| 11 | moaz maged   |   Smouha    |    2001     |
+----+------+---------------------+-------------+
| 12 | mazen mahmod |   elmasry   |    2006     |
+----+------+---------------------+-------------+
| 13 | ahmed shawky |   Petroget  |    2002     |
+----+------+---------------------+-------------+
| 14 | shaker ali   |   Petroget  |    2007     |
+----+------+---------------------+-------------+

我尝试使用查询来过滤数据库中的数据

select full_name,club_name from players where y_of_birth=2000

结果是5玩家应该是这样的:

+--------------+--------------+
|   full_name  |  club_name   |
+--------------+--------------+
| Ahmed Sayed  |   El Ahly    |
+----+------+--+--------------+
| Kareem Gaber |   El Ahly    |
+------+-------+--------------+
| Kamal saber  |  wadi dgla   |
+------+-------+--------------+
| omar galal   |   Cocorico   |
+------+-------+--------------+
| Mohamed gad  |  Ismaily     |
+------+-------+--------------+

好的条件是:

如果结果超过 4 > 4 <8> <= 8将结果放入8我们的案例中结果是5它意味着8 - 5 = 3意味着迭代这个单词3次,结果应该是这样的:

+--------------+-------------+
|   full_name  |  club_name  |
+--------------+-------------+
| Ahmed Sayed  |  El Ahly    |
+----+------+--+-------------+
| **ANY WORD** |             |
+--------------+-------------+
| Kareem Gaber |  El Ahly    |
+------+-------+-------------+
| Kamal saber  |  wadi dgla  |
+------+-------+-------------+
| **ANY WORD** |             |
+--------------+-------------+ 
| omar galal   |  Cocorico   |
+------+-------+-------------+
| Mohamed gad  |  Ismaily    |
+------+-------+-------------+
| **ANY WORD** |             |
+--------------+-------------+

注意:请不要在**ANY WORD**与上述示例之间相邻:

+------+-------+
| **ANY WORD** |
+--------------+
| **ANY WORD** |
+--------------+

club_name与上述示例之间没有相邻:

+------+-------+
|    El Ahly   |
+--------------+
|    El Ahly   |
+--------------+

已更新:

再次举例

基于这些数字

4 8 16 32 64 128 256

并且条件是:

  1. 如果查询结果&lt; = 4和&gt; 2表示(4 - the number of query result)
  2. 示例:如果查询结果为3,那么4 - 3 = 1因此1**ANY WORD**的数字,所以所需的输出就像那个:

    +--------------+-------------+
    |   full_name  |  club_name  |
    +--------------+-------------+
    | Ahmed Sayed  |  El Ahly    |
    +----+------+--+-------------+
    | **ANY WORD** |             |
    +--------------+-------------+
    | Kareem Gaber |  El Ahly    |
    +------+-------+-------------+
    | Kamal saber  |  wadi dgla  |
    +--------------+-------------+
    
    1. 另一个示例 8 如果查询结果&lt; = 8和&gt; 4表示(8 - the number of query result)
    2. 例如: 查询结果5所以8 - 5 = 3因此3**ANY WORD**的数字,因此所需的输出将是那样的

      +--------------+-------------+
      |   full_name  |  club_name  |
      +--------------+-------------+
      | Ahmed Sayed  |  El Ahly    |
      +----+------+--+-------------+
      | **ANY WORD** |             |
      +--------------+-------------+
      | Kareem Gaber |  El Ahly    |
      +------+-------+-------------+
      | Kamal saber  |  wadi dgla  |
      +------+-------+-------------+
      | **ANY WORD** |             |
      +--------------+-------------+ 
      | omar galal   |  Cocorico   |
      +------+-------+-------------+
      | Mohamed gad  |  Ismaily    |
      +------+-------+-------------+
      | **ANY WORD** |             |
      +--------------+-------------+
      

      依旧使用416以及3264 ..等到256

      非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

使用变量并使用来自here的基本相同技巧的新增和改进(第3版):

SELECT
  IF(is_real, '**ANY WORD**', full_name) AS full_name,
  IF(is_real, '', club_name) AS club_name
FROM
  (
    SELECT
      full_name,
      club_name,
      (@row_num2:= @row_num2 + 1) AS row_num
    FROM
      (
        SELECT p3.*
        FROM
          (
        SELECT
          p2.*,
          (@row_num := @row_num + 1) AS row_num
        FROM
          (
            SELECT *
            FROM players AS p1
            WHERE y_of_birth = 2000
          ) AS p2
        CROSS JOIN
          (
            SELECT
              @row_num := 0,
              @count := (SELECT COUNT(*) FROM players WHERE y_of_birth = 2000)
          ) AS vars
        ORDER BY club_name
      ) AS p3
    ORDER BY row_num % FLOOR(@row_num / 2), row_num
  ) AS p4
CROSS JOIN
  (
    SELECT
      @row_num2 := -1,
      @extra := GREATEST(2, POW(2, CEIL(LOG2(@count)))) - @count) AS vars
  ) AS data
LEFT JOIN
  (
    (SELECT 1 AS is_real)
    UNION ALL
    (SELECT 0 AS is_real)
  ) AS filler
ON
  MOD(row_num, FLOOR(@count / @extra)) = 0 AND
  row_num / FLOOR(@count / @extra) < @extra
ORDER BY row_num, is_real

对于您提供的示例数据,这会产生如下内容:

+--------------+-----------+
| full_name    | club_name |
+--------------+-----------+
| Ahmed Sayed  | El Ahly   |
| **ANY WORD** |           |
| Mohamed gad  | Ismaily   |
| **ANY WORD** |           |
| omar galal   | Cocorico  |
| **ANY WORD** |           |
| Kareem Gaber | El Ahly   |
| Kamal saber  | wadi dgla |
+--------------+-----------+

这适用于任何规模的结果;只需将条件(y_of_birth = 2000)更改为您想要的任何条件。我升级到MySQL 5.6来测试它(实际上它实际上产生了一些小的差异)。

基本技巧是使用1然后0创建一个包含静态值的两行表(在本例中为UNIONLEFT JOIN)实际结果需要多次填充2的幂。这意味着我们已经计算了结果中每一行的数量(称为row_num),这样我们就可以正确地形成连接条件。最后,每隔这么多行产生一个重复的行;最后一点是通过检查我们是在真实的还是假的(IF1)行来更改我们在这些重复项上选择的内容(使用0)。

这可以防止同一支球队的球员彼此相邻,除非这是不可能的,因为一支球队的球员太多;请参阅上面的链接,了解有关如何操作的更多信息。基本的想法是通过俱乐部订购,然后从该列表的上半部分和后半部分进行备选。

最后的诀窍是弄清楚虚拟行中加入的数量和位置。在尝试了几件事之后,我意识到这实际上非常简单:只需连接每一行,直到达到所需数量的虚拟行(@extra)。但是,这会将所有虚拟行打包在结果的顶部;更广泛地传播它们(不是完全展开,而是更加分散),计算我们需要多少次添加一个(FLOOR(@count / @extra)),然后每隔多行放一个({{1}的第一部分)条件)直到添加足够的(第二部分)。

答案 1 :(得分:2)

以下过程将返回4列。应显示第一列和第二列。第三列只是应该忽略的rownum。如果第四列不是空白,则在下一行显示,否则不显示。

DELIMITER //
create procedure test()
BEGIN
declare N int;
declare X int;
select count(*) from players where y_of_birth=2000 into N;
set X = power(2,ceil(log2(N))) -N;
SELECT full_name, club_name, @row := @row + 1 AS row, 
case when (@row<= X) 
then 'any word' else '' end r
FROM players, (SELECT @row:=0) z
where y_of_birth=2000;
END //
DELIMITER 

call test;