单个表上的MySQL复杂查询问题

时间:2011-08-10 07:57:47

标签: mysql select nested

尝试了几种可能性后,我停下来了。没有用数百个查询重载mysql服务器,这就是我想要实现的目标:

这是表格

    CREATE TABLE `users` (
  `id` int(11) NOT NULL auto_increment,
  `firstname` varchar(64) NOT NULL,
  `lastname` varchar(64) NOT NULL,
  `email` varchar(64) NOT NULL,
  `status` smallint(5) NOT NULL,
  `refchid1` int(11) NOT NULL,
  `refchid2` int(11) NOT NULL,
  `refchid3` int(11) NOT NULL,
  `refchid4` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

说明:

  1. 我正在尝试根据复杂的树调整一个人的状态。每个用户都有一个id,由auto_increment id字段表示。
  2. 用户A将他的详细信息输入表中。
  3. 用户B由用户A提及,因此当输入其详细信息时,refchid1具有与用户A相同的ID。
  4. 用户C由用户B提及,他的refchid1成为用户B的id,他的refchid2成为用户A的id。
  5. 用户D由用户C提及,他的refchid1变为用户C,refchid2为UserB,refchid3为用户A。
  6. 如果您理解上述内容的参考,那么您就走在了正确的轨道上。

    以上描述的样本数据:

    (6, 'Lars', 'Luna', 'Morbi.non.sapien@enimgravida.com', 25, 0, 0, 0, 0),
    (7, 'Sonya', 'Cox', 'tellus@orci.org', 25, 6, 0, 0, 0),
    (8, 'Aiko', 'Hodge', 'vestibulum.neque.sed@vel.edu', 25, 7, 6, 0, 0),
    (9, 'Lillith', 'Bray', 'purus.Duis.elementum@necurnasuscipit.org', 25, 8, 7, 6, 0),
    (10, 'Macey', 'Hayes', 'mi.pede@aliquetodioEtiam.net', 25, 9, 8, 7, 6);
    

    我想要完成的是:

    1. 默认状态为25.(25,28,30,35,40)这基本上看作是一个折扣系统,你引用的人越多,他们所引用的人越多,你的原始引用者就越多折扣。
    2. 如果用户A至少有10个唯一用户,他引用了refchid1,他就获得了状态。
    3. 如果用户A在refchid1中至少有10个uniuque用户,每个用户在refchid1中有10个唯一用户,其中用户A是refchid2,则他获得状态。
    4. 用户A在rechid1中有10个唯一用户,每个用户在refchid1中有10个唯一用户,其中用户A是rechid2,而refchid1中有10个唯一用户,其中用户A是refchid3。
    5. 如上所述,测试结构很复杂,我希望这样做,而不会使数百万个查询重载mysql服务器。查询应该是一个UPDATE查询,它将调整所有匹配用户的状态。

      有没有人能解决我将如何实现这一目标?

3 个答案:

答案 0 :(得分:1)

我真的不知道你是如何计算得分的,但是这个查询可能会给你足够的数据来使用,玩它并在你得到公式时将其重写为更新查询。

SELECT
 parent.*,
 SUM(IF(parent.id = child.refchid1, 1, 0)) AS count_ref1,
 SUM(IF(parent.id = child.refchid2, 1, 0)) AS count_ref2,
 SUM(IF(parent.id = child.refchid3, 1, 0)) AS count_ref3,
 SUM(IF(parent.id = child.refchid4, 1, 0)) AS count_ref4,
 COUNT(child.id) as count_ref
FROM users AS parent 
LEFT JOIN users AS child 
    ON (  parent.id = child.refchid1 
       OR parent.id = child.refchid2 
       OR parent.id = child.refchid3 
       OR parent.id = child.refchid4)
GROUP BY parent.id

答案 1 :(得分:0)

你有没有想过triggers? 当您直接在表的行上更新状态而不是通过视图动态生成它(我更喜欢)时,我认为触发插入操作然后创建正确的“if”语句可能是个好主意。

否则我建议不要使用 status refchid *列,但只有一个 refid 引用“父”ID然后使用生成状态值的视图(关于refidivelyly refid)。

答案 2 :(得分:0)

我应该创建一个用户列表,以及一个单独的参考表,

CREATE TABLE reference
(
    reference_id SERIAL,
    new_user_id BIGINT UNSIGNED NOT NULL,
    refered_user_id BIGINT UNSIGNED NOT NULL,
    reference_depth INT UNSIGNED NOT NULL
);

当您添加新用户时,如果该用户被其他用户引用,请添加一行白色深度1,

INSERT INTO reference SET
    new_user_id = $new_user_id, 
    refered_user_id =  $refered_user_id, 
    reference_depth = 1

然后选择链接到该用户的所有引用并添加深度whit 1:

INSERT INTO reference (new_user_id, refered_user_id, reference_depth)
SELECT $new_user_id, refered_user_id, reference_depth +1
FROM reference WHERE new_user_id = $refered_user_id;

然后计算点数

SELECT
  SUM(
    IF(reference_depth = 1, 10, 0) 
    + IF(reference_depth = 2, 3, 0) 
    + IF(reference_depth = 3, 2, 0)
    + IF(reference_depth > 3, 1, 0)
  )
FROM reference
WHERE new_user_id = $user_id