简体   繁体   中英

Aggregate MySQL data, am using group by, but it isn't quite doing what I want

I have a community driven database for an iOS game. I am trying to aggregate the data I've collected by the community, and it looks something like this:

+--------+--------+--------------+
| color1 | color2 | result_color |
+--------+--------+--------------+
| red    | blue   | purple       |
| blue   | red    | purple       |
| red    | blue   | purple       |
| yellow | blue   | green        |
+--------+--------+--------------+

Currently, I am running the following query:

select
    count(*) as count,
    `Mixes`.*
from
    `mixes` AS `Mixes`
where
    `result_color` = 'purple'
group_by
    color1,
    color2
order by
    `count` desc

Which produces the following output:

+-------+--------+--------+--------------+
| count | color1 | color2 | result_color |
+-------+--------+--------+--------------+
| 2     | red    | blue   | purple       |
| 1     | blue   | red    | purple       |
+-------+--------+--------+--------------+

However, I would like it to produce the following output, since when mixing colors it doesn't matter which color you mix first:

+-------+--------+--------+--------------+
| count | color1 | color2 | result_color |
+-------+--------+--------+--------------+
| 3     | red    | blue   | purple       |
+-------+--------+--------+--------------+

So, my question is, how can I aggregate data over 2 columns such that when color1 is red and color2 is blue, that the aggregate function treats it the same as when color1 is blue and color2 is red?

Thanks in advance!

If you just have the two color columns you can simply order them with a CASE expression:

SELECT
  COUNT(*) AS `count`,
  CASE WHEN color1 < color2 THEN color1 ELSE color2 END AS color1,
  CASE WHEN color1 >= color2 THEN color1 ELSE color2 END AS color2,
  resultcolor
FROM mixes
WHERE resultcolor = 'purple'
GROUP BY
  CASE WHEN color1 < color2 THEN color1 ELSE color2 END,
  CASE WHEN color1 >= color2 THEN color2 ELSE color1 END,
  resultcolor
ORDER BY `count`;

here is the logic that I have in mind and you need to implement it..

You basically have a inner select query that selects the required final select columns, plus a new custom column called color, which is basically a concatenation of color1 and color2 but with the added logic that the lexicographically smaller string is concatenated with the larger string always which can be done using a switch/if statement in SQL.

thus your custom color column will look like bluered for both the rows.

and now you have an outer query that groups by this custom column and you should get your desired output.

The SQL for the comparison and select should be as follows:

SELECT CASE WHEN STRCMP(color1,color2)<=0 THEN color2+''+color1 ELSE color1+''+color2 END
FROM Mixes
WHERE result_color='purple'

Hope that works. I might try and write the entire SQL query if I am feeling good about myself..

Also I did not understand the reason for grouping it by the two colors when you can just group it by the result_color but I tried to answer your question as you have asked (may be you have your reasons)

Try this

SELECT COUNT(*) AS `Count`, M.*
FROM
(SELECT
  CASE WHEN color1 < color2 THEN color1 ELSE color2 END AS color1,
  CASE WHEN color1 > color2 THEN color1 ELSE color2 END AS color2,
  result_color
FROM mixes
WHERE result_color = 'purple') M
GROUP BY M.color1, M.color2
ORDER BY
    `Count` DESC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM