MySQL выбрать строки с одинаковыми идентификаторами и сохранить их порядок? - PullRequest
1 голос
/ 23 февраля 2012

просто быстрый вопрос:

У меня должен быть один запрос с несколькими строками - некоторые строки идентичны - и порядок строк должен быть сохранен в результате -

некоторое представление о том, что я имею в виду:

SELECT id,date 
FROM items 
WHERE id IN (1,2,1,3) 
ORDER BY id=1 DESC,id=2 DESC,id=1 DESC,id=3 DESC;

к сожалению MySQL результат таков:

1,2,3

не 1,2,1,3

удаляет дубликаты, которые я должен иметь в своем результате для отображения на нескольких панелях на одной веб-странице -

Я действительно не хочу циклически проходить по каждому идентификатору один за другим, чтобы получить их так, как я хочу отобразить -

есть ли способ на самом деле иметь один-единственный запрос, который будет сохранять порядок и извлекать строки на основе запроса независимо от того, уникален он или нет -

Ответы [ 6 ]

1 голос
/ 23 февраля 2012

Другой подход (не проверенный, но должен дать вам идею):

CREATE TEMPORARY TABLE tt (id INT, ai int unsigned auto_increment primary key);
INSERT INTO tt (id) VALUES (1), (2), (1), (3);
SELECT
    id,
    date
FROM items JOIN tt USING (id)
ORDER BY tt.ai;

сохраняет заданный порядок.

1 голос
/ 23 февраля 2012

Еще один скрупулезный способ ответить на подозрительный вопрос:

SELECT 
      items.id, 
      items.date 
FROM 
      items 
  JOIN
      ( SELECT 1 AS id, 1 AS ordering
      UNION ALL 
        SELECT 2, 2
      UNION ALL 
        SELECT 1, 3
      UNION ALL 
        SELECT 3, 4
      ) AS auxilary
    ON 
      auxilary.id = items.id 
ORDER BY 
      auxilary.ordering
1 голос
/ 23 февраля 2012

1001 * попробовать *

SELECT
    id,
    date
FROM items
WHERE id IN (1,2,1,3)
ORDER BY FIND_IN_SET(id, '1,2,1,3')
1 голос
/ 23 февраля 2012

Ваш запрос в его нынешнем виде никогда не будет работать, поскольку повторяющиеся значения в списке значений предложения IN игнорируются. только способ сделать эту работу - использовать UNION ALL:

SELECT id, date FROM items where id = 1
UNION ALL
SELECT id, date FROM items where id = 2
UNION ALL
SELECT id, date FROM items where id = 1
UNION ALL
SELECT id, date FROM items where id = 3;

Но, честно говоря, я подозреваю, что ваша модель данных до сих пор не использовалась.

1 голос
/ 23 февраля 2012

Если вы хотите включить записи с id = 1 и порядок не имеет значения, пока вы их получаете, вы можете разделить ваш запрос на два запроса, один для (1,2,3) объединения всех остальныхзапрос для id = 1 или просто выполните:

... In (1,2)
Union all
... In (1,3)

Пример:

  Select * from
  (Select case id when 1 then 1 when 2 then 2 as pseudocol, othercolumns
  From table where Id in (1,2)
  Union all
  Select case id when 1 then 3 when 3 then 4 as pseudocol, othercolumns
  From table where Id in (1,3)) t order by pseudocol
1 голос
/ 23 февраля 2012

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

После того, как вы это сделаете, вы можете использовать логику внешнего интерфейса.выводить их в нужном порядке, включая дубликаты.Это уменьшит объем избыточных данных, которые вы пытаетесь выбрать.

Например, Это неиспользуемый код - точный синтаксис зависит от вашего языка сценариев

-- setup a display order
displayOrder= [1,2,1,3];

-- select data from database, order doesn't matter here
SELECT id,date 
FROM items 
WHERE id IN (displayOrder);


-- cache the results in a key=> value array
arrCachedRows = {};
for (.... each db row returned ...) {
    arrCachedRows[id] = date;
}

-- Now output in desired order
for (listIndex in displayOrder) {
    -- Make sure the index is cached
    if (listIndex exists in arrCachedRow) {
        echo arrCachedRows[listIndex ];
    }
}

Если вы должны продолжать использовать UNION, несмотря на мои предупреждения

Если вы идете против вышеуказанной рекомендации и абсолютно ДОЛЖНЫ вернуть их в 1 запросе в таком порядке, то добавьте дополнительную строку, которая будетобеспечить порядок строк.Смотрите ниже запрос, где я использую переменную @subIndex, чтобы добавить инкрементное значение как subIndex.Это, в свою очередь, позволяет вам изменить порядок в соответствии с этим, и он будет в запрошенном порядке.

SELECT
    i.*
FROM (
    SELECT @subIndex:=@subIndex+1 AS subIndex, id, date FROM items where id = 1
    UNION
    SELECT @subIndex:=@subIndex+1 AS subIndex, id, date FROM items where id = 2
    UNION
    SELECT @subIndex:=@subIndex+1 AS subIndex, id, date FROM items where id = 1
    UNION
    SELECT @subIndex:=@subIndex+1 AS subIndex, id, date FROM items where id = 3
) AS i,(SELECT @subIndex:=0) v
ORDER BY i.subIndex

Или немного более чистая версия, которая сохраняет выбор элементов до внешней стороны и скрывает субиндекс

SELECT
    items.*
FROM items
-- initialise variable
INNER JOIN (SELECT @subIndex:=0) v
-- create a meta-table with the ids desired in the order desired
INNER JOIN (
    SELECT @subIndex:=@subIndex+1  AS subIndex, 1 AS id
    UNION
    SELECT @subIndex:=@subIndex+1  AS subIndex, 2 AS id
    UNION
    SELECT @subIndex:=@subIndex+1  AS subIndex, 1 AS id
    UNION
    SELECT @subIndex:=@subIndex+1  AS subIndex, 3 AS id
) AS i
ON i.id = items.id
-- order by the subindex from i
ORDER BY i.`subIndex` ASC
...