【问题标题】:Multiple joins in mysql with 3 tablesmysql中的多个连接与3个表
【发布时间】:2020-07-28 15:17:52
【问题描述】:

我有 3 张桌子

branch-
  br_id,
  br_name

users 
 user_id
 user_name
 user_type (2 types 'owner' 'admin')
 user_branch (associated branch )
 user_branches (comma seperated branch ids in case of 'admin' type )

item 
  it_id
  it_amount
  it_owner
  it_admin 
  it_activated

这里每个项目都由用户类型“所有者”拥有

每个项目还通过用户类型“admin”关联

我想要的是 分行列表及相关的总量和总数

**Branch**             **total**  **total amount**
some branch Name    5   500
another Branch Name 7   780

我怎样才能在单个查询中做到这一点

我试过这个显示所有分支的数量

SELECT br_name,
count(it_id),
SUM(it_amount),
FROM branch
LEFT JOIN users ON FIND_IN_SET(br_id,user_branches)>0
LEFT JOIN item ON it_admin=ad_id
WHERE it_activated=1
GROUP BY br_name

但我在所有分支机构中的数量和数量都相同

【问题讨论】:

  • 感谢您为回答问题所做的任何尝试。
  • 你试过什么了吗???
  • 花一些时间创建一个小提琴:db-fiddle.com 并提供足够的样本数据并发布预期结果以澄清。
  • user_branches,作为一个以逗号分隔的字符串表示 values,是危险的,因为不是normalized。专门为用户分支制作另一个表可能会很有用
  • 我们两个人花时间回答了您的问题 - 您愿意回复@DRapp 和我自己吗?

标签: mysql sql database join


【解决方案1】:

首先,您确实应该提供最低限度,尤其是在提出赏金请求时。不了解您的表格结构和示例内容会使其他人更难提供帮助。我创建了示例创建表和插入,然后是查询。如有不准确之处请指正。

CREATE TABLE branch (
  br_id int unsigned NOT NULL,
  br_name varchar(10) NOT NULL,
  PRIMARY KEY (br_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE users (
  user_id int unsigned NOT NULL,
  user_name varchar(10) NOT NULL,
  user_type varchar(10) NOT NULL,
  user_branch int NOT NULL,
  user_branches varchar(10) NOT NULL,
  PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE item (
  it_id int unsigned NOT NULL,
  it_amount int NOT NULL,
  it_owner int NOT NULL,
  it_admin int NOT NULL,
  it_activated int NOT NULL,
  PRIMARY KEY (it_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into branch ( br_id, br_name )
  values 
  ( 1, 'b1' ), 
  ( 2, 'b2'), 
  ( 3, 'b3' );

insert into users ( user_id, user_name, user_type, user_branch, user_branches )
  values 
  ( 1, 'n1', 'owner', 1, '' ),
  ( 2, 'n2', 'admin', 2, '2, 3' ),
  ( 3, 'n3', 'owner', 3, '' );

insert into item ( it_id, it_amount, it_owner, it_admin, it_activated )
  values
  ( 1, 100, 1, 2, 1 ),
  ( 2, 150, 3, 2, 1 ),
  ( 3, 125, 1, 2, 1 ),
  ( 4, 30, 3, 2, 0 );

现在,我认为您需要的是一个 UNION 查询,分别涵盖所有者和管理员,否则,您将得到全面的双重计算。其次,当您使用逗号分隔的列表来保存某人/某物可以符合条件的多个 ID(例如您的 ADMIN 用户)时,我认为这不是最好的表格设计布局。但如果这就是你所拥有的并且无法改变它,那就这样吧。

所以,现在开始查询。逐一查看。如果按 OWNER 类型的用户进行查询,则仅加入该用户类型并专门绑定到用户的分支,然后根据项目的所有者绑定到项目表。你得到一个结果。

最后,类似的加入,但仅基于用户的ADMIN类型,并根据项目的ADMIN ID加入项目。

同样,如果没有您的示例源记录和预期输出,这是我目前(可能还有其他人)能想到的最佳解释。因此,对于类似列结果结构中的查询,它们可以与“UNION”组合在一起。我添加了一个额外的列来显示数字的来源,分别基于所有者/管理员的来源。

select
        b.br_name,
        'By Owner' Source,
        count(i.it_id) numOfItems,
        SUM(i.it_amount) sumOfAmount
    FROM
        branch b
            JOIN Users u
                on u.user_type = 'owner'
                AND b.br_id = u.user_branch
                JOIN Item i
                    on u.user_id = i.it_owner
                    AND i.it_activated = 1
    group by
        b.br_name
UNION        
select
        b.br_name,
        'By Admin' Source,
        count(i.it_id) numOfItems,
        SUM(i.it_amount) sumOfAmount
    FROM
        branch b
            JOIN Users u
                on u.user_type = 'admin'
                AND FIND_IN_SET(b.br_id, u.user_branches) > 0
                JOIN Item i
                    on u.user_id = i.it_admin
                    AND i.it_activated = 1
    group by
        b.br_name;
        

【讨论】:

    【解决方案2】:

    我不确定你想从查询中得到什么,所以我猜测了一下。我的答案查询查找链接到每个分支的项目的总计数和总金额,首先按所有者,然后按管理员。

    在您的查询中,您有一个字段“ad_id”:

        LEFT JOIN item ON it_admin=ad_id
    

    我认为这意味着“user_id”?

    我还注意到,在您的查询中,您根本没有引用所有者。如果您实际上只是通过管理员从链接到分支的项目中查找结果,那么您可以删除/忽略以下查询中的前两个子查询:

           SELECT   br_name as branchname,
                (SELECT COUNT( DISTINCT it_id) 
                    FROM item i1 
                    JOIN users u1 ON i1.it_owner = u1.user_id AND i1.it_activated=1
                    WHERE u1.user_branch = b.br_id AND u1.user_type = "owner") as ownertotal,
                (SELECT COUNT( DISTINCT it_id) 
                    FROM item i2 
                    JOIN users u2 ON i2.it_admin = u2.user_id AND i2.it_activated=1
                    WHERE FIND_IN_SET(b.br_id, u2.user_branches) != 0 AND u2.user_type = "admin") as admintotal ,
                (SELECT SUM(i3.it_amount) 
                    FROM item i3 
                    JOIN users u3 ON i3.it_owner = u3.user_id AND i3.it_activated=1
                    WHERE u3.user_branch = b.br_id AND u3.user_type = "owner") as owneramount,
                (SELECT SUM(i4.it_amount) 
                    FROM item i4 
                    JOIN users u4 ON i4.it_admin = u4.user_id AND i4.it_activated=1
                    WHERE FIND_IN_SET(b.br_id, u4.user_branches) != 0 AND u4.user_type = "admin") as adminamount
        FROM branch b;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-05
      • 1970-01-01
      • 2013-04-07
      • 2013-04-21
      • 2023-03-03
      • 2017-06-30
      相关资源
      最近更新 更多