我正在使用MySQL。我有一张看起来像这样的表:
id: primary key
name: varchar
weight: int (this can be either 1,2 or 3)
我想要做的是随机选择一行,直到我从一个类似下面有500行的表中获得400个选定行的列表,但考虑到了权重。
For example, if I have 3 rows:
id, name, weight
1, "some content", 2
2, "other content", 1
3, "something", 3
创建列表时,权重为2的行在列表中出现30%的次数,权重为1的行在列表中出现20%的次数,权重为3的行出现50%的次数在列表中。
允许重复,但不允许重复。
有办法吗?
如果您不了解某些内容,请随时提出。
提前致谢。
答案 0 :(得分:1)
我仍然没有解决重复部分。但这会给你一个开始
<强> SQL Fiddle Demo 强>
50% Weight = 3
SELECT `ID`,`Name`,`Weight`, RowNumber
FROM (
SELECT *,
@row_num := IF(@prev_value = `Weight`,
@row_num + 1,
IF(@prev_value:=`Weight`,
1,
1)
) AS RowNumber
FROM (
SELECT `ID`,`Name`,`Weight`, rand() as rng
FROM `myTable`
ORDER BY `Weight`, rng
) X
CROSS JOIN (SELECT @row_num := 1, @prev_value := 0) y
) T
WHERE ( Weight = 3 and RowNumber <= 50 * 0.5 )
OR ( Weight = 2 and RowNumber <= 50 * 0.3 )
OR ( Weight = 1 and RowNumber <= 50 * 0.2 )
ORDER BY Weight, RowNumber
答案 1 :(得分:0)
我建议您制作一个临时表,其中1个记录的所有记录重复2次,2个记录的记录重复3次,所有3个记录重复5次。然后在所有记录中的临时表中进行随机选择。如果总数足够大(例如400),这在统计上应该最终得到非常接近目标的分布。
答案 2 :(得分:0)
在我的另一个答案中,我解决了如何为每个重量分配ID。在这里,我将向您展示如何创建一个列表来处理重复项。
我使用表格来显示整个过程,您也可以选择演示来验证每个结果。但是有些工作可以在一个查询中合并,但不容易阅读。
<强> SQL FIDDLE DEMO 强>
首先,我们需要创建一个表来存储哪一行将参与您的列表
CREATE TABLE `incr` (
`weight` mediumint,
`row` mediumint
);
使用存储过程我们填写表格。
CREATE PROCEDURE dowhile(IN Size INT)
BEGIN
DECLARE v1 INT DEFAULT Size * 0.5;
WHILE v1 >= 0 DO
IF v1 <= (Size - 1) * 0.5 THEN
INSERT incr VALUES (3, v1);
END IF;
IF v1 <= (Size - 1) * 0.3 THEN
INSERT incr VALUES (2, v1);
END IF;
IF v1 <= (Size - 1) * 0.2 THEN
INSERT incr VALUES (1, v1);
END IF;
SET v1 = v1 - 1;
END WHILE;
END//
CALL dowhile(300); -- Indicate List Size
现在创建一个新表,以了解我们样本中每个权重类别的大小。
CREATE TABLE maxWeight
SELECT `Weight`, COUNT(*) as mw
FROM `myTable`
GROUP BY `Weight`;
使用%
运算符,我们可以重复这些行来填充所需的大小
CREATE TABLE rowList
SELECT i.weight,
CASE WHEN i.row >= w.mw then i.row % w.mw
ELSE i.row
END newrow
FROM incr i
JOIN maxWeight w
ON i.weight = w.weight;
正如您在此处所见,即使我的列表仅为100,最终结果为300
SELECT weight, count(*)
FROM rowList
GROUP BY weight;
| weight | count(*) |
|--------|----------|
| 1 | 60 |
| 2 | 90 |
| 3 | 150 |
现在将两个表连接在一起
CREATE TABLE finalResult
SELECT `ID`,`Name`, T.`Weight`, RowNumber
FROM (
SELECT *,
@row_num := IF(@prev_value = `Weight`,
@row_num + 1,
IF(@prev_value:=`Weight`,
0,
0)
) AS RowNumber
FROM (
SELECT `ID`,`Name`,`Weight`, rand() as rng
FROM `myTable`
ORDER BY `Weight`, rng
) X
CROSS JOIN (SELECT @row_num := 0, @prev_value := 0) y
) T
JOIN rowList
ON T.`RowNumber` = rowList.`newrow`
AND T.`Weight` = rowList.`weight`;
最终结果是使用重复名称
的欲望比率SELECT `Weight`, COUNT(*) total, COUNT(DISTINCT `Name`) d_name
FROM finalResult
GROUP BY `Weight`;
| Weight | total | d_name |
|--------|-------|--------|
| 1 | 60 | 36 |
| 2 | 90 | 32 |
| 3 | 150 | 30 |
即使原始表格有37 weight = 1
,我用来生成随机值的工具也会复制一个名称,因此d_name = 36