Возможно создать запрос MySQL, который отображает только те вещи, которые находятся в порядке убывания - PullRequest
4 голосов
/ 23 июля 2011

Для начала я хочу прояснить, что я не пытаюсь упорядочить по убыванию.

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

Пример:

Ordered by column-------------------Descending Column
353215                                    20
535325                                    15
523532                                    10
666464                                    30
473460                                    20

Если бы я получил эти данные, я бы хотел, чтобы они возвращали только 20, 15 и 10. Потому что теперь, когда 30 больше 10, нам все равно, что под ними.

Я искал везде и не могу найти решение.

Ответы [ 6 ]

2 голосов
/ 23 июля 2011

РЕДАКТИРОВАТЬ: удалил большое число init и edd счетчик в тесте ifnull, поэтому он работает в чистом MySQL: ifnull(@prec,counter), а не ifnull(@prec,999999).

Если ваш старттаблица t1, и базовый запрос был:

select id,counter from t1 order by id;

Затем с помощью mysql-переменной вы можете выполнить работу:

SET @prec=NULL;
select * from (
    select id,counter,@prec:= if(
       ifnull(@prec,counter)>=counter,
       counter,
       -1) as prec
    from t1 order by id
 ) t2 where prec<>-1;

за исключением здесь Iнужно 99999 в качестве максимального значения для вашего столбца , и, возможно, есть способ поместить инициализацию @prec в NULL где-нибудь в 1-м запросе.

Здесь столбец prec содержит счетчик значений 1-й строки, а затем значение счетчика каждой строки, если оно меньше, чем значение из предыдущей строки, и -1, если это становится ложным.

Обновить

Внешний выбор можетбыть полностью удаленным, если назначение переменной выполняется в предложении WHERE:

SELECT @prec := NULL;
SELECT
  id,
  counter
FROM t1
WHERE
  (@prec := IF(
    IFNULL(@prec, counter) >= counter,
    counter,
    -1
  )) IS NOT NULL
  AND @prec <> -1
ORDER BY id;

regilero РЕДАКТИРОВАТЬ: Я могу удалить 1-й запрос инициализации, используя временную таблицу (левое соединение)1 строка таким образом: но это может замедлить запрос, может быть.

(...)
FROM t1 
LEFT JOIN (select @prec:=NULL as nullinit limit 1) as tmp1 ON tmp1.nullinit is null
(..)

Как сказал @Mike, используя простой запрос UNION или даже:

(...)
FROM t1 , (select @prec:=NULL) tmp1 
(...)

лучше, если вы хотите избежать первого запроса.

Итак, в конце самое хорошее решение:

SELECT NULL AS id, NULL AS counter FROM dual WHERE (@prec := NULL) 
UNION
SELECT   id,   counter
FROM t1  
WHERE   (
   @prec := IF(
      IFNULL(@prec, counter) >= counter,
      counter,
      -1   )) IS NOT NULL
AND @prec <> -1
ORDER BY id;

+--------+---------+
| id     | counter |
+--------+---------+
| 353215 |      20 |
| 523532 |      10 |
| 535325 |      15 |
+--------+---------+

ОБЪЯСНИТЬ ВЫБРАТЬ вывод:

+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
| id | select_type  | table      | type | possible_keys | key  | key_len | ref  | rows | Extra            |
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
|  1 | PRIMARY      | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE | 
|  2 | UNION        | t1         | ALL  | NULL          | NULL | NULL    | NULL |    6 | Using where      | 
| NULL | UNION RESULT | <union1,2> | ALL  | NULL          | NULL | NULL    | NULL | NULL | Using filesort   | 
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
2 голосов
/ 23 июля 2011

Вы не нашли решение, потому что это невозможно.

SQL работает только внутри строки, он не может просматривать строки выше или ниже его.

Вы можете написать сохраненныйДля этого нужно выполнить одну строку за раз и вычислить логику.

Вероятно, было бы проще написать это на языке интерфейса, независимо от того, что вы используете.

1 голос
/ 23 июля 2011

Я не уверен, что они делают то, что вы хотите, и, вероятно, они все равно слишком медленные:

SELECT t1.col1, t1.col2
  FROM tbl t1
  WHERE t1.col2 = (SELECT MIN(t2.col2) FROM tbl t2 WHERE t2.col1 <= t1.col1)

Или

SELECT t1.col1, t1.col2
  FROM tbl t1
  INNER JOIN tbl t2 ON t2.col1 <= t1.col1
  GROUP BY t1.col1, t1.col2
  HAVING t1.col2 = MIN(t2.col2)
1 голос
/ 23 июля 2011

Боюсь, вы не можете сделать это в SQL. Реляционные базы данных были разработаны для различных целей, поэтому в них нет абстракции, как в следующей или предыдущей строке. Сделайте это вне SQL на языке «оберток».

0 голосов
/ 23 июля 2011

Это на самом деле возможно, но производительность нелегко оптимизировать.Если Col1 упорядочен, а Col2 - нисходящий столбец:

Сначала вы создаете самостоятельное объединение каждой строки со следующей строкой (обратите внимание, что это работает только в том случае, если значение столбца уникально, если нет необходимости присоединяться куникальные значения).

(Select Col1, (Select Min(Col2) as A2 from MyTable as B Where B.A2>A.Col1)  As Col1FromNextRow From MyTable As A) As D
INNER JOIN
(Select Col1 As C1,Col2 From MyTable As C On C.C1=D.Col1FromNextRow)

Затем вы реализуете бит "продолжайте до первого возрастающего значения":

Select Col2 FROM
(
(Select Col1, (Select Min(Col2) as A2 from MyTable as B Where B.A2>A.Col1)  As Col1FromNextRow From MyTable As A) As D
INNER JOIN
(Select Col1 As C1,Col2 From MyTable As C On C.C1=D.Col1FromNextRow)
) As E
WHERE NOT EXISTS
(SELECT Col1 FROM MyTable As Z Where z.COL1<E.Col1 and Z.Col2 < E.Col2)

У меня нет среды для тестирования, поэтомувероятно, есть ошибки.Мои извинения, но, надеюсь, идея наполовину ясна.

Я все равно попытался бы сделать это вне SQL.

0 голосов
/ 23 июля 2011

Полагаю, вы могли бы выбрать их (по порядку) во временную таблицу, которая также имеет столбец с автоинкрементом, а затем выбрать из временной таблицы, объединяясь с самим собой на основе столбца с автоинкрементом (id), но где t1.id = t2.id + 1, а затем используйте критерии where (и соответствующий порядок по и предел 1), чтобы найти t1.id строки, в которой нисходящий столбец больше в t2, чем в t1.После чего вы можете выбрать из временной таблицы, где идентификатор меньше или равен идентификатору, который вы только что нашли.Это не совсем красиво, хотя!:)

...