MySQL - PERL - Упорядочить по нескольким столбцам, затем упорядочить по полю номера детали столбца - PullRequest
1 голос
/ 17 февраля 2011
id|pnumber|special|limitedtime|normal
1 |765234 |1      |0          |0
2 |765235 |0      |1          |0
3 |776234 |0      |0          |1
4 |776235 |1      |0          |0
5 |785456 |0      |1          |0
6 |785457 |1      |0          |0

Вот еще один сценарий проблемы, которую я опубликовал ранее.

Обратите внимание, что я на самом деле использую dbi и заполнители, но использую только основы для моего вопроса.

Вместо трех запросов:

SELECT `pnumber` from `table`
WHERE `special` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar2

выполнить и отобразить

SELECT `pnumber` from `table`
WHERE `limitedtime` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar2

выполнить и отобразить

SELECT `pnumber` from `table`
WHERE `normal` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar2

выполнить и отобразить

Что дает мои результаты, но ЛИМИТ должен быть привязан ко всем трем /dependent.

Итак, я хочу сделать что-то вроде:

SELECT `pnumber` from `table`
ORDER BY special?? ABS(pnumber) DESC,
ORDER BY limitedtime?? ABS(pnumber) DESC,
ORDER BY normal?? ABS(pnumber) DESC
LIMIT $Lvar1,$Lvar2

Что, я думаю, если все сделано правильно, даст мне мои результаты в порядке, который я желаю.

765234 (special)
776235 (special)
785457 (special)
765235 (limitedtime)
785456 (limitedtime)
776234 (normal)

Я использую LIMIT $ Lvar1, $ Lvar2 для разбивки на страницы / навигации.

(В таблице гораздо больше данных, результаты на самом деле помещаются в массивы, потому что есть некоторые перекрестные ссылки / запросы к другим таблицам, происходящие позже в коде.)

Конечно, это большой вопрос, на который кто-то может ответить простым вот здесь, иди!

Спасибо за помощь всем этим новичкам.

Ответы [ 3 ]

1 голос
/ 17 февраля 2011

Вы можете использовать оператор объединения, чтобы объединить три выбора, затем выполнить порядок и ограничение.

SELECT `pnumber` from `table`
WHERE `special` > 1
union
SELECT `pnumber` from `table`
WHERE `limitedtime` > 1
union
SELECT `pnumber` from `table`
WHERE `normal` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar2
1 голос
/ 17 февраля 2011

Вы можете просто использовать union all, чтобы объединить выходные данные запросов

SELECT `pnumber` from `table`
WHERE `special` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar2

UNION ALL

SELECT `pnumber` from `table`
WHERE `limitedtime` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar

UNION ALL

SELECT `pnumber` from `table`
WHERE `normal` > 1
ORDER BY ABS(pnumber) DESC 
LIMIT $Lvar1,$Lvar

Union All по существу берет выходные данные запросов и объединяет их.

0 голосов
/ 17 февраля 2011

Я вижу некоторые несоответствия с данными вашего примера.Вы ищете вещи со специальным, ограниченным или нормальным значением, которые имеют значения> 1, но ваш примерный набор данных имеет только значения 1. Вы никогда не получите никаких результатов из этого набора данных вообще, потому что ничто никогда не будет соответствовать предложению WHERE.

Кроме того, вы задаете предложения ORDER BY с помощью DESC, но в примере, который вы хотите видеть в качестве результата, вы показываете их отсортированными по возрастанию.

Я собираюсь сделать двапредположения здесь:

1) Вы на самом деле хотите, чтобы их значения были> 0, а не> 1 (если вам нужно только ненулевое значение, запрос становится проще, но поскольку вы специально использовали ABS () IЯ предполагаю, что реальные данные, с которыми вы работаете, могут иметь отрицательные значения).

2) Вы действительно имели в виду ASC, а не DESC, поскольку запрашиваемый вывод находится в таком порядке.

Поэтому, используя данные, которые вы указали выше, будет работать следующий запрос:

  SELECT pnumber,
         CONCAT('(',
                CONCAT_WS(', ',
                          IF(special > 0, 'special', NULL),
                          IF(limitedtime > 0, 'limited time', NULL),
                          IF(normal > 0, 'normal', NULL)),
                ')') AS type_desc,
         IF(special > 0, 3, 0) + IF(limitedtime > 0, 2, 0) + IF(normal > 0, 1, 0) AS disp_priority
    FROM ex_table
   WHERE ((special > 0) + (limitedtime > 0) + (normal > 0)) > 0
ORDER BY disp_priority DESC,
         ABS(pnumber) ASC

Не требуется UNION.Также обратите внимание, что UNION может не дать вам того, что вы ищете в любом случае: если вы используете один из примеров UNION, показанных выше, то в случае, когда оба специальных> 0 И ограниченное время> 0 вы получите дублирующую строку вывода,так как он будет соответствовать более чем одному из запросов UNION.

Приведенный ниже запрос выводит в монитор MySQL следующее:

+---------+----------------+---------------+
| pnumber | type_desc      | disp_priority |
+---------+----------------+---------------+
|  765234 | (special)      |             3 | 
|  776235 | (special)      |             3 | 
|  785457 | (special)      |             3 | 
|  765235 | (limited time) |             2 | 
|  785456 | (limited time) |             2 | 
|  776234 | (normal)       |             1 | 
+---------+----------------+---------------+
6 rows in set (0.23 sec)

И, за исключением дополнительного выходного столбца,это именно то, что вы просили сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...