How to get multiple records against one record based on relation?

前端 未结 8 724
遇见更好的自我
遇见更好的自我 2020-11-29 09:11

I have two tables Organisation and Employee having one to many relation i.e one organisation can have multiple employees. Now I want to select all information of a particula

相关标签:
8条回答
  • 2020-11-29 09:12

    The original question was database specific, but perhaps this is a good place to include a more generic answer. It's a common question. The concept that you are describing is often referred to as 'Group Concatenation'. There's no standard solution in SQL-92 or SQL-99. So you'll need a vendor-specific solution.

    • MySQL - Probably the simplest solution. Use the built-in GROUP_CONCAT function. In your example you would want something like this:
    select 
      o.ID, o.Address, o.OtherDetails,
      GROUP_CONCAT( concat(e.firstname, ' ', e.lastname) ) as Employees
    from 
      employees e 
      inner join organization o on o.org_id=e.org_id
    group by o.org_id
    
    • PostgreSQL - EDIT: PostgreSQL 9.0 is equally simple now that string_agg(expression, delimiter) is built-in. Here it is with 'comma-space' between elements:
    select 
      o.ID, o.Address, o.OtherDetails,
      STRING_AGG( (e.firstname || ' ' || e.lastname), ', ' ) as Employees
    from 
      employees e 
      inner join organization o on o.org_id=e.org_id
    group by o.org_id
    

    PostgreSQL before 9.0 allows you to define your own aggregate functions with CREATE AGGREGATE. Slightly more work than MySQL, but much more flexible. See this other post for more details. (Of course PostgreSQL 9.0 and later have this option as well.)

    • Oracle & MS SQL Server - Create a stored procedure that takes the org_id as its input and outputs the concatenated employee names. Then use this stored procedure in your query. Some of the other responses here include some details about how to write stored procedures like these.
    select 
      o.ID, o.Address, o.OtherDetails,
      MY_CUSTOM_GROUP_CONCAT_PROCEDURE( o.ID ) as Employees
    from 
      organization o
    
    • Other DBMS technologies - The stored procedure route is the most likely. Perhaps others can update this answer with more technology specific answers.
    0 讨论(0)
  • 2020-11-29 09:13

    It all depends. If you do a join, you get all the organization data on every row. (1 row per employee). That has a cost. If you do two queries. (Org and Emp) that has a different cost.

    Pick your poison.

    0 讨论(0)
  • 2020-11-29 09:15

    For SQL Server SQLCLR aggregates in this project are inspired by the MSDN code sample however they perform much better and allow for sorting (as strings) and alternate delimiters if needed. They offer almost equivalent functionality to MySQL's GROUP_CONCAT for SQL Server.

    A full comparison of the advantages/disadvantages of the CLR aggregates and the FOR XML solution can be found in the documentation:

    http://groupconcat.codeplex.com

    0 讨论(0)
  • 2020-11-29 09:16

    in MS SQL you can do:

    create function dbo.table2list (@input int)
    returns varchar(8000)
    as
    BEGIN
    declare @putout varchar(8000)
    set @putout = ''
    select @putout = @putout + ', ' + <employeename>
    from <employeetable>
    where <orgid> = @input
    return @putout
    end
    

    then do:

    select * from org, dbo.table2list(orgid)
    from <organisationtable>
    

    I think you can do it with COALESCE() as well, but can't remember the syntax off the top of my head

    0 讨论(0)
  • 2020-11-29 09:18

    Since the question is tagged as MySQL, you should be able to use a MySQL-specific solution, namely, GROUP_CONCAT. For example,

    select Org_ID, Org_Address, Org_OtherDetails,
           GROUP_CONCAT(employees) as Employees
    from  employees a, organization b
    where a.org_id=b.org_id
    group by b.org_id;
    
    0 讨论(0)
  • 2020-11-29 09:20

    Here's what you can do, you have 2 options:

    select *
    FROM
      users u
      LEFT JOIN organizations o ON (u.idorg = o.id);
    

    This way you will get extra data on each row - full organization info you don't really need.

    Or you can do:

    select o.*, group_concat(u.name)
    FROM
      users u
      LEFT JOIN organizations o ON (u.idorg = o.id)
    GROUP BY
      o.id
    

    http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

    The second approach is applicable if you want to see ie. list of usernames "user1, user2, user3", but don't want to operate on the fields themselves...

    0 讨论(0)
提交回复
热议问题