SELECT,如何将某些行合并为一个,首先显示具有特定列值的行并排除行

时间:2018-04-08 12:15:09

标签: mysql sql join group-by

我有两个表,unitspower。  看看:

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,对于单行和行都应该相同,这是行中多行的总和。如您所见,在结果集中,排除了ID为1的行。 id是由应用程序提供的,我认为在MySQL中做它比在PHP中做得更好,因为MySQL可能只丢弃这一行(我认为),但是使用PHP它必须做if()检查每个循环迭代,似乎效率较低。

  2. 每次在单行之前显示summed-rows行。

  3. 每次在其他用户之前显示用户的单位。您可以看到 user_id 10 的行(想象此用户是看到该页面的用户)首先出现在我的结果集中。

  4. 首先显示功率最高的单位。

  5. 首先显示金额最高的单位。

  6. 首先显示内容最高的单位。

  7. 最后一个(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 = 页面上访问此单元列表。然后我单独选择输入的ID用于此目的我的应用程序,然后选择列表。但由于我已经输入了id的数据(例如,在这种情况下为1),当我从units和{{1}中选择时,我不需要它们}}

    @匿名,回答你的问题1,回答1是:所有具有相同group_id的行(0除外是power标记)被分组并组合在一起,因此行为not-a-group45具有相同的6。我的问题是,我不知道如何排除独立行(没有组标记)的分组以及如何对结果进行排序,以便对具有指定user_id的行进行排序,然后分组行(4,5,6-转-to-4)也先排序,但在user_id = 10-first,user_id = ?? - 第二层次结构,如果这是有意义的。

1 个答案:

答案 0 :(得分: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应首先显示在列表中,而不是在您的示例中。