Làm cách nào để thực hiện một NHÓM B BYNG phức tạp trong MySQL?


8

Tôi có một bảng chứa một số khóa vào các bảng khác (trong đó mỗi khóa bao gồm nhiều cột). Tôi muốn có thể nhóm các hàng lại với nhau có khóa bằng nhau, nhưng tôi không muốn nhóm tất cả chúng lại với nhau. Nó không đơn giản GROUP BYtrên khóa mà là tôi muốn có thể tạo các nhóm nói 10. Vì vậy, nếu một khóa cụ thể xuất hiện 50 lần tôi sẽ nhận được 5 kết quả khi tôi thực hiện nhóm này (5 nhóm 10). Tôi cũng muốn nhóm này xảy ra ngẫu nhiên trong khóa.

Tôi không biết cách trực tiếp để làm điều này và phương pháp đường vòng mà tôi nghĩ ra không hiệu quả như tôi nghĩ nó nên làm. Giải pháp bùng binh mà tôi đã đưa ra là tạo một cột mới cho mỗi khóa sẽ là một số nguyên sao cho giá trị đó ibiểu thị ithsự xuất hiện của khóa đó (nhưng theo thứ tự ngẫu nhiên). Sau đó tôi có thể thực hiện phép chia số nguyên sao cho mọi n (nói 10) hàng trong khóa có cùng giá trị và tôi có thể thực hiện một GROUP BYgiá trị đó.

Có cách nào trực tiếp hơn để thực hiện những gì tôi vừa mô tả? Điều này khá khó xử và tôi gặp vấn đề trong việc tạo cột chỉ mục mới (như tôi đã mô tả trong câu hỏi này ).

EDIT: Trước hết lưu ý rằng đây là dành cho MySQL. Tôi sẽ thêm một ví dụ trong trường hợp mục tiêu của tôi không rõ ràng. Các tài liệu MySQL hiển thị một phương thức để đạt được gần đó :

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

Điều này tạo ra một bảng, mặc dù không phải là những gì tôi muốn, được đóng lại:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

Về cơ bản tôi muốn GROUP BYid, ngoại trừ tôi muốn các bản ghi mammalcó một "nhóm" cho ID 1-10, một "nhóm" khác cho ID 11-20, v.v. Tuy nhiên, tôi sẽ làm điều này với một bảng hiện có, và tôi không nhất thiết muốn "con chó" xuất hiện với ID 1. Tôi muốn thứ tự ban đầu là ngẫu nhiên, nhưng sau đó sẽ mang tính quyết định.


I would want that initial ordering to be random, but then deterministic from then out.<- nói gì? Tôi nghĩ bất kể bạn làm gì, bạn sẽ phải đặt các bản ghi vào một bảng thứ hai. Làm thế nào chính xác logic kinh doanh này hoạt động? Như không có gì để yêu cầu (ví dụ) con chó đến trước. Và ý của bạn là gì I would want the records from *mammal* to have one "group" for IDs 1-10, and another for IDs 11-20... bạn có thể minh họa điều đó bằng một bảng khác, tập trung vào động vật có vú, trong phần mô tả câu hỏi trên không?
jcolebrand

@jcolebrand Với mỗi bản ghi là động vật có vú tôi muốn chỉ định một id duy nhất từ ​​1 đến numMammal. Tôi không thực sự quan tâm id dognhận được gì , nhưng tôi không muốn nó phụ thuộc vào thứ tự chèn ban đầu.
Michael McGowan

@jcolebrand Giả sử tôi cũng có một cột cân. Tôi có thể muốn lấy trọng lượng trung bình của động vật có vú với ID từ 1-10 và trọng lượng trung bình của động vật có vú từ ID 11-20, v.v ... Đó là ý nghĩa mà tôi muốn GROUP BY. Sau đó tôi có thể muốn ghép các nhóm 10 để tìm mối tương quan giữa mức trung bình. Tôi cần thứ tự ngẫu nhiên này bởi vì nếu thứ tự chèn ban đầu tình cờ được sắp xếp theo trọng lượng thì điều này sẽ cho tôi kết quả sai. Tôi hy vọng tôi có ý nghĩa.
Michael McGowan

Tôi vẫn nghĩ rằng một BẢNG mẫu trong câu hỏi sẽ hữu ích. Nhưng tôi nghĩ rằng tôi thấy những gì bạn muốn. Tôi chỉ không thấy những thứ đó là miền của SQL, vì nó không thực sự là về các tập hợp. SQL là miền của các tập hợp. Tôi sẽ làm logic mà bạn đề xuất trong một tệp php với một (hoặc hai) vòng lặp. SQL sẽ thực hiện một vòng lặp đơn hiệu quả để gán các số dù sao.
jcolebrand

@jcolebrand Có thể là tôi không nên làm điều này trong SQL, nhưng tôi nghĩ một quy tắc hữu ích là để cơ sở dữ liệu thực hiện công việc cho bạn. Tôi vẫn đang tìm hiểu các giới hạn về những gì nên và không nên được xử lý trong cơ sở dữ liệu, nhưng trước đây khi tôi thử rút kết quả, xử lý chúng và sau đó đưa kết quả trở lại, tôi đã nhận được kết quả hoạt động kém (giờ và giờ vì tôi có thể đã làm gì đó sai khi chèn kết quả lại).
Michael McGowan

Câu trả lời:


5

Điều gì về việc làm một bài toán nhỏ chống lại cột ID của bạn để tạo động nhóm?

SELECT grp, FLOOR(id/10) AS id_grp
FROM animals
GROUP BY grp, id_grp

Điều này sẽ cung cấp cho bạn nhóm 10 dựa trên ID của hồ sơ. Tôi đã sử dụng bảng động vật của bạn ở trên để tạo ra dữ liệu dưới đây.

Dữ liệu mẫu

 INSERT INTO animals VALUES
 ('mammal',10,'dog'),('mammal',11,'dog'),('mammal',12,'dog'),
 ('mammal',21,'cat'),('mammal',22,'cat'),('mammal',23,'cat'),
 ('mammal',24,'cat'),('mammal',25,'cat'),('mammal',26,'cat'),
 ('bird',30,'penguin'),('bird',31,'penguin'),('bird',32,'penguin'),
 ('bird',33,'penguin'),('fish',44,'lax'),('fish',45,'lax'),
 ('fish',46,'lax'),('fish',47,'lax'),('fish',48,'lax'),
 ('mammal',31,'whale'),*'fish',51,'lax'),('fish',52,'lax'),
 ('fish',53,'lax'),('fish',54,'lax'),('bird',10,'ostrich');

Đầu ra truy vấn

 +--------+--------+
 | grp    | id_grp |
 +--------+--------+
 | fish   |      4 |
 | fish   |      5 |
 | mammal |      1 |
 | mammal |      2 |
 | mammal |      3 |
 | bird   |      1 |
 | bird   |      3 |
 +--------+--------+
 7 rows in set (0.00 sec)

Tôi đã lên kế hoạch làm toán tương tự nếu lần đầu tiên tôi có thể tạo bảng trong câu hỏi. Tôi gặp sự cố khi nhận ID được gán chính xác.
Michael McGowan

Điều này có giúp ích gì cho tất cả @MichaelMcGowan không? explainextended.com/2009/03/05/row-sampling hoặc jimlife.wordpress.com/2008/09/09/...
jcolebrand

@jcolebrand Cảm ơn, tôi vẫn đang xem liên kết đầu tiên. Tôi đã thử một cách tiếp cận tương tự như liên kết thứ 2 và gặp vấn đề với nó: dba.stackexchange.com/questions/1932/ợi
Michael McGowan

2

Trong SQL nói chung, điều này sẽ là:

  • một mục phụ DISTINCT
  • THAM GIA trở lại bảng chính trên các phím DISTINCT
  • NTILE với THAM GIA B onNG các phím DISTINCT và ĐẶT HÀNG B toNG để tạo các thùng

Nó không phải là tổng hợp nên NHÓM THEO không cần thiết

Biên tập:

Trên thực tế, NTILE là đủ để tạo ra "n nhóm trên mỗi bộ giá trị riêng biệt"


Tôi không tin MySQL hỗ trợ NTILE.
Michael McGowan

Xin lỗi, liên kết đó ngụ ý nó. Có lẽ có một giải pháp / cách giải quyết cho NTILE ngoài kia.
gbn

Giải pháp tuyệt vời của Oracle.
Leigh Riffel

@Leigh Riffel: và Máy chủ SQL. Và Sybase. Và PostGres ...
gbn

2
@gbn Không phải MySQL là điểm tôi nên làm rõ. Bài viết tham khảo Oracle.
Leigh Riffel

1

Tôi vẫn chưa thấy bất kỳ giải pháp hoàn chỉnh nào (thực sự hoạt động trong MySQL), vì vậy đây là giải pháp tôi có thể sẽ sử dụng:

  1. Tạo hoàn toàn ID ngẫu nhiên bên ngoài SQL (trong một số loại tập lệnh)
  2. Áp dụng phân chia số nguyên trên các ID đó để nhóm chúng.

Tôi vẫn hy vọng ai đó có thể đánh bại câu trả lời này; Tôi không muốn phải chấp nhận câu trả lời của riêng tôi. Tôi đã nói điều này trước đây, nhưng tôi đã biết từ đầu cách làm # 2; # 1 là những gì đã gây phiền toái cho tôi. Nếu bạn có thể trả lời # 1 thì bạn thực sự cũng trả lời một câu hỏi khác , nhưng có thể trả lời câu hỏi này theo một cách khác để bỏ qua # 1.


0
-- Change 'ValueField' to whatever provides your 'group' values

set @rownum := 0;
set @groupnum := 0;
set @lastGroup := 0;

select
    ValueField, 
    Grouping, 
    count(1) as Count
from
    (
        -- We have a row number for each record
        select
            -- Set the record number
            case when @lastGroup != ValueField 
                then @rownum := 0 else (@rownum := @rownum + 1) 
            end as Record, 

            -- Determine which group we are in
            case
                -- If the 'Group' changed, reset our grouping
                when @lastGroup != ValueField 
                    then @groupnum := 0

                -- Determines the grouping value; group size is set to 10
                when floor(@rownum / 10) != @groupnum 
                    then @groupnum := @groupnum + 1 
                else @groupnum
            end as Grouping,

            -- Track the last Group
            case 
                when @lastGroup != ValueField 
                    then @lastGroup := ValueField 
                else @lastGroup 
            end as LastGroup,

            -- Value field that will be aggregated
            ValueField 
        from 
            YourTable
        order by 
            ValueField
    ) as x
group by
    ValueField, 
    Grouping;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.