sql >> Database >  >> RDS >> Mysql

SQL - print veel woorden tussen elke kolom met veel voorwaarden

Nieuw en verbeterd (versie 3 hoe) met variabelen en in principe dezelfde truc van hier :

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

Voor de voorbeeldgegevens die u gaf, levert dit iets op als:

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

Dit zou voor elk resultaat moeten werken; verander gewoon de voorwaarde (y_of_birth = 2000 ) om in welke staat dan ook te zijn. Ik heb geüpgraded naar MySQL 5.6 om dit te testen (het bleek eigenlijk een klein verschil te maken).

De basistruc is om een ​​tabel met twee rijen te maken met statische waarden (in dit geval 1 en 0 ) met een UNION en dan LEFT JOIN dat in de werkelijke resultaten een aantal keren moet vullen tot een macht van 2. Dit betekent dat we het aantal van elke rij in het resultaat hebben berekend (genaamd row_num ) zodat we de join-voorwaarde goed kunnen formuleren. Uiteindelijk levert dit om de zoveel rijen een dubbele rij op; het laatste deel is om te veranderen wat we selecteren op die duplicaten (met behulp van IF s) door te controleren of we een echte of neppe zijn (1 of 0 ) rij.

Dit moet voorkomen dat spelers van hetzelfde team naast elkaar staan, tenzij dit onmogelijk is omdat een team te veel spelers heeft; zie de link hierboven voor meer informatie over hoe dat te doen. Het basisidee is om per club te bestellen en vervolgens afwisselend te kiezen uit de eerste helft en de tweede helft van die lijst.

De laatste truc was om erachter te komen hoeveel en waar je in de dummy-rijen moest meedoen. Na verschillende dingen geprobeerd te hebben, realiseerde ik me dat dit eigenlijk heel eenvoudig is:sluit gewoon aan bij elke rij totdat we het gewenste aantal dummy-rijen hebben bereikt (@extra ). Dat zal echter alle dummy-rijen bovenaan de resultaten inpakken; om ze meer te spreiden (niet perfect gespreid, maar meer gespreid), bereken hoe vaak we er een moeten toevoegen (FLOOR(@count / @extra) ) en plaats er vervolgens één om de zoveel rijen (het eerste deel van de ON voorwaarde) totdat er genoeg zijn toegevoegd (het tweede deel).



  1. Doe mee aan een telquery op generation_series() en haal null-waarden op als '0'

  2. Sql Server string tot datum conversie

  3. Krijg envelop.i.e overlappende tijdspannes

  4. Controleren of een niet-LOB-kolom moet worden bijgewerkt