SQL - печатать много слов между каждым столбцом со многими условиями
Сначала у меня есть неизменяемые значения:
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
и условие :
- если результат запроса <=
4
и > 2
означает (4 - the number of query result)
пример:, если результат запроса 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 |
+--------------+-------------+
- другой пример с
8
если результат запроса <= 8
и > 4
означает (8 - the number of query result)
например:
результат запроса равен 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** | |
+--------------+-------------+
и т.д. с 4
и 16
и 32
и 64
..etc до 256
.
Любая помощь будет высоко оценена.
Ответы
Ответ 1
Новый и улучшенный (вариант 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
) с использованием UNION
, а затем LEFT JOIN
, что в фактических результатах несколько раз заполнить до степени 2. Это означает, что мы вычислили количество каждой строки в результате (называемое row_num
), чтобы мы могли корректно сформулировать условие соединения. В конце концов, это создает повторяющуюся строку каждые столько строк; последний бит должен изменить то, что мы выбираем на этих дубликатах (используя IF
s), проверяя, находимся ли мы в реальной или поддельной строке (1
или 0
).
Это должно препятствовать тому, чтобы игроки из одной команды находились рядом друг с другом, если это невозможно, потому что в одной команде слишком много игроков; см. ссылку выше для получения дополнительной информации о том, как это сделать. Основная идея состоит в том, чтобы заказать по клубу, а затем чередовать сборку с первой половины и второй половины этого списка.
Последний трюк состоял в том, чтобы выяснить, сколько и где присоединиться к фиктивным строкам. Попробовав несколько вещей, я понял, что это на самом деле очень просто: просто присоединитесь к каждой строке, пока мы не достигнем желаемого количества фиктивных строк (@extra
). Тем не менее, это упакует все фиктивные строки в верхней части результатов; чтобы раскрыть их больше (не совсем разбросанные, но более распространенные), подсчитайте, как часто нам нужно добавить один (FLOOR(@count / @extra)
), а затем поместить один каждый, что много строк (первая часть условия ON
), пока (вторая часть).
Ответ 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;