简体   繁体   中英

Group two columns by occurrence and sort by time in MYSQL

I am working with a table that contains a list of uploaded files that will be processed by a Laser Cutter.

To increase efficiency I need to list files that have the same material and colour in order of how many of the same combination occurs. Then order that by the time it was sent.

Here is a very simplified table example:

文件表示例

From the example table above I want to achieve the following results:

6    File Number 6    Plastic    Red     9am
4    File Number 4    Plastic    Red     10am
5    File Number 5    Plastic    Red     10:30am
1    File Number 1    Card       Blue    9am
2    File Number 2    Card       Blue    9:30am
7    File Number 7    Plastic    Purple  8am
3    File Number 3    Card       Green   9am

So where both material and colour occur the most, the respective rows are at the top and within that, the earliest file is at the top.

As you can see, red plastic occurs the most so is at the top. Single files are ordered by time only as seen with file 7 and 3.

Ideally I would like to perform this in one MYSQL query but given its complexity I'm not sure that will be possible. Perhaps storing the results and looping through arrays?

I have nearly managed to achieve this with this query:

SELECT * 
FROM propellor.pro_files 
GROUP BY material, colour 
ORDER BY count(*) DESC, 
   material DESC, 
   colour DESC, 
   sent DESC;

Although this seems to be ordered almost correctly it only returns single rows for each material/colour combination.

It's worth noting that the colour column can be null .

For an idea of how I'm grouping them, here's how it will look in practice:

分组示例

UPDATE: The material / colour groups are ordered correctly now but single files are ordered newest to oldest when I need it the other way around, I have tried playing with sent ASC / DESC but it only affects files in a group.

排序示例

UPDATE 2: Here is my current full MYSQL query:

SELECT * 
FROM propellor.pro_files

INNER JOIN propellor.pro_users ON propellor.pro_files.userid=propellor.pro_users.userid

INNER JOIN (
SELECT material, colour, count(*) AS occ 
FROM propellor.pro_files
GROUP BY material, colour
) 

AS mcCounts 
USING (material, colour)
WHERE status =1 AND laser=1
ORDER BY mcCounts.occ DESC,
material,
colour,
propellor.pro_files.timesent ASC
;

You need to calculate the counts separately, though it can all be done in a single query; this should do it:

SELECT pf.* 
FROM propellor.pro_files AS pf
INNER JOIN (
   SELECT material, colour, count(*) AS occ 
   FROM propellor.pro_files
   GROUP BY material, colour 
) AS mcCounts USING (material, colour)
ORDER BY mcCounts.occ DESC
   , material, colour
   , pf.sent DESC
;

Edit: Added material, colour to ORDER BY... for when two combinations have the same frequency.

You can try creating count columns in your sql select and then ordering by those counts

select count(material) over partition by material) as materialCount
       , count(colour) over partition by colour) as colourCount
       , ..... other columns
from   propellor.pro_files
order by materialCount desc, colourcount 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