SELECT, как объединить несколько строк в одну, сначала показать строки с определенным значением столбца и исключить строку

0

У меня есть две таблицы, units и power. Взгляни на:

Таблица power:

+----+-------+
| id | power |
+----+-------+
|  1 |     2 |
|  2 |     4 |
|  3 |     6 |
|  4 |     8 |
+----+-------+

Таблица units:

 +----+---------+----------+--------+----------+---+---+
    | id | user_id | power_id | amount | group_id | x | y |
    +----+---------+----------+--------+----------+---+---+
    |  1 |      10 |        3 |   1000 |        0 | 1 | 1 |
    |  2 |      10 |        3 |   1000 |        0 | 1 | 1 |
    |  3 |      10 |        3 |   1000 |        0 | 1 | 1 |
    |  4 |      11 |        2 |    100 |        4 | 1 | 1 |
    |  5 |      11 |        2 |    100 |        4 | 1 | 1 |
    |  6 |      11 |        1 |    100 |        4 | 1 | 1 |
    |  7 |      12 |        4 |   1000 |        0 | 1 | 1 |
    +----+---------+----------+--------+----------+---+---+

Я хочу получить результат, выглядящий следующим образом:

+----------+--------------+-------------+----------+---------+--+
| units.id | total_amount | total_power | group_id | user_id |  |
+----------+--------------+-------------+----------+---------+--+
|        3 |         1000 |        6000 |        0 |      10 |  |
|        2 |         1000 |        6000 |        0 |      10 |  |
|        4 |          300 |        1000 |        4 |      11 |  |
|        7 |         1000 |        8000 |        0 |      12 |  |
+----------+--------------+-------------+----------+---------+--+

Объяснение:

  1. Исключить конкретный идентификатор, должен работать одинаково как для одной строки, так и для строки, которая представляет собой сумму нескольких строк в таблице. Как видите, в результирующем наборе исключалась строка с id 1. Идентификатор предоставлен приложением, я думаю, что лучше сделать это в MySQL, чем PHP, потому что MySQL может просто отбросить эту строку (я думаю), но с PHP это должно было бы сделать if() проверку для каждой итерации цикла, которая кажется менее эффективным.

  2. Показывать строку суммированных строк перед отдельными строками каждый раз.

  3. Показывать пользовательские блоки перед другими пользователями, каждый раз. Вы можете видеть, что когда строки с user_id из 10 (представьте, что этот пользователь является тем, кто видит страницу), сначала появляются в моем результирующем наборе.

  4. Сначала покажите единицы с максимальной мощностью.

  5. Сначала показывайте единицы с наивысшим количеством.

  6. Показывать единицы с наивысшим идентификатором.

Последние (4.5.6) сортируются относительно приоритета результирующего набора, причем четвертый имеет наибольшую часть. У меня есть этот запрос:

SELECT   units.id,
         units.amount*power.power AS total_power,
         Sum(units.amount)        AS total_amount
FROM     units
JOIN     power
ON       units.power_id = power.id
WHERE    x = ?
AND      y = 1
GROUP BY group_id
ORDER BY group_id desc, total_power desc, total_amount desc, units.id desc limit ?,?

Но он объединяет все единицы, где group_id равно 0, однако я хочу, чтобы единицы с group_id=0 были отдельными строками в наборе результатов. Как это сделать? Спасибо!

Изменить: Чтобы ответить на вопрос @Linoff о том, как я определяю, какой id для исключения, я исключаю 1 в примере, потому что пользователь всегда увидит результирующий набор, обратившись к нему с помощью unit_id, что опять же в моем примере 1, Надеюсь, теперь это ясно. Изменить: пользователь может получить доступ к этому списку единиц на странице " index.php? Page = unit/view & id =. Затем я ВЫБРАТЬ введенный идентификатор отдельно для моего приложения, а затем ВЫБЕРИТЕ список. Но поскольку у меня уже есть данные для введенного идентификатора (например, 1 в этом случае) мне не нужно иметь их, когда я ВЫБИРАЮ из units и power.

@Anonymous, чтобы ответить на ваш вопрос 1, ответ 1: все строки с одинаковым group_id (кроме 0, который является маркером not-a-group) сгруппированы и объединены вместе, поэтому строки, которые являются идентификаторами 4, 5 и 6 которые имеют одинаковые group_id объединены. Моя проблема заключается в том, что я не знаю, как исключить группировку для строк, которые являются автономными (без групповой маркировки) и как сортировать результат, поэтому строки с указанным user_id сначала сортируются и группируются по строкам (4,5,6-оборотные -to-4) также сортируются сначала, но в user_id = 10-first, user_id =?? -second иерархии, если это имеет смысл.

  • 2
    То, как вы определяете строки в вашем наборе результатов, совершенно сбивает меня с толку. Если «1» отбрасывается, почему не «2»? Строки точно такие же.
  • 0
    Я не получаю этого суммирования, но покажу их отдельно. Либо вы группируете запрос, либо нет, но у вас не может быть обоих способов. Для этого вам нужно использовать два запроса, которые можно объединить во внешнем запросе, но может быть проще сделать это в php.
Показать ещё 8 комментариев
Теги:
join
group-by

1 ответ

0

Я думаю, это то, что вы хотите:

CREATE TABLE Power  (id int,  power int);
CREATE TABLE demo (id integer primary key, name varchar(20), hint text);
CREATE TABLE units (id, user_id, power_id, amount, group_id, x, y);

SELECT   1 as spec2_HIDETHIS,  /* Spec 2 show the groupedrows first */
         units.id    as units_ID,
         units.amount*power.power AS total_power,
         units.amount        AS total_amount,
         units.group_id      as group_id
FROM     units
JOIN     power
ON       units.power_id = power.id
WHERE    units.group_id=0  /*  */
AND      units.id != 1  /* Spec no 1 : exclud specific id */
union 
SELECT   0 as spec2_HIDETHIS,  /* Spec 2 show the groupedrows first */
         min(units.id) as units_ID ,
         units.amount*power.power AS total_power,
         Sum(units.amount)        AS total_amount,
         units.group_id           as group_id
FROM     units
JOIN     power
ON       units.power_id = power.id
where    units.group_id > 0
AND      units.id != 1  /* Spec no 1 : exclud specific id */
GROUP BY group_id
ORDER BY spec2_HIDETHIS, group_id desc, total_power desc, total_amount desc, units_ID desc  

Fiddle Link, вам нужно щелкнуть по бегу, чтобы получить результаты.

То, что я не понимаю, - это спецификация 2: "показать сгруппированные перед негруппированными". Это означает, что единицы id 4 должны отображаться сначала в списке, чего нет в вашем примере.

  • 0
    Спасибо! Я придумал похожий запрос, но я все еще не знаю, как обратиться к третьей спецификации, то есть я хочу, чтобы строки набора результатов появлялись первыми (до применения любых других спецификаций, таких как 4), если у них есть определенный user_id. В данном случае это 10. Мне нужно это, чтобы сначала показать пользователю их юниты. Правильно ли я предполагаю, что мне нужно будет выполнить отдельный запрос или другой UNION или есть лучший способ?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню