SQL - print many word between every columns with many conditions

后端 未结 2 1245
眼角桃花
眼角桃花 2021-01-04 11:51

Ok first i have immutable values :

4   8   16   32   64   128   256

and i have one table something like that :

+----+------         


        
相关标签:
2条回答
  • 2021-01-04 12:38

    New and improved (version 3 how) using variables and using basically the same trick from here:

    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
    

    For the example data you gave, this produces something like:

    +--------------+-----------+
    | 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 |
    +--------------+-----------+
    

    This should work for any size result; just change the condition (y_of_birth = 2000) to be whatever condition you want. I upgraded to MySQL 5.6 to test this (it actually turned out to make a small difference).

    The basic trick is to create a two-row table with static values (in this case, 1 and 0) using a UNION and then LEFT JOIN that into the actual results some number of times to fill up to a power of 2. This means we have calculate the number of each row in the result (called row_num) so that we can formulate the join condition properly. In the end, this produces a duplicate row every so many rows; the final bit is to change what we select on those duplicates (using IFs) by checking if we are on a real or fake (1 or 0) row.

    This should prevent players from the same team being next to each other unless this is impossible because one team has too many players; see the link above for more about how to do that. The basic idea is to order by club and then alternate picking from the first half and the second half of that list.

    The final trick was to figure out how many and where to join in the dummy rows. After trying several things, I realized that this is actually very easy: just join with every row until we have reached the desired number of dummy rows (@extra). However, that will pack all the dummy rows at the top of the results; to spread them out more (not perfectly spread out, but more spread out), calculate how often we need to add one (FLOOR(@count / @extra)) and then put one every that many rows (the first part of the ON condition) until enough have been added (the second part).

    0 讨论(0)
  • 2021-01-04 12:47

    The following procedure will return 4 columns. The first and second columns should be displayed. The third column is just the rownum which should be ignored. If the fourth column is not blank then display it in the next row otherwise don't display it.

    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;
    
    0 讨论(0)
提交回复
热议问题