连接两个以上的表而不重复值

时间:2017-12-31 16:15:24

标签: sql sql-server

我想加入三张桌子,

我有三个表用户,专业和教育,其中" uid"是其他两个表的用户表和外键的主键。我想加入这些表以在一个表中生成结果

user              profession           education
+------+-------+  +-----+----------+  +-----+---------+
| uid  | uName |  | uid | profName |  | uid | eduName |
+------+-------+  +-----+----------+  +-----+---------+
|    1 | aaa   |  |   1 | prof1    |  |   1 | edu1    |
|    2 | bbb   |  |   1 | prof2    |  |   1 | edu2    |
|    3 | ccc   |  |   2 | prof1    |  |   1 | edu3    |
|      |       |  |   3 | prof3    |  |   3 | edu4    |
|      |       |  |   3 | prof2    |  |     |         |
+------+-------+  +-----+----------+  +-----+---------+


Expected output
+------+-------+-----+----------+-----+---------+
| uid  | uName | uid | profName | uid | eduName |
+------+-------+-----+----------+-----+---------+
|    1 | aaa   |   1 | prof1    |   1 | edu1    |
| null | null  |   1 | prof2    |   1 | edu2    |
| null | null  |null | null     |   1 | edu3    |
|    2 | bbb   |   2 | prof1    | null| null    |
|    3 | ccc   |   3 | prof3    |   3 | edu4    |
| null | null  |   3 | prof2    | null| null    |
+------+-------+-----+----------+-----+---------+

我尝试了以下查询

select u.uid ,u.uName,p.uid , p.profName,e.uid,e.eduName
from  user  u inner join profession p on u.uid=p.pid
inner join education e on u.uid = e.uid
where u.uid=p.uid
and u.uid=e.uid
and i.uid=1

这给了我重复的值

+------+-------+-----+----------+-----+---------+
| uid  | uName | uid | profName | uid | eduName |
+------+-------+-----+----------+-----+---------+
|    1 | aaa   |   1 | prof1    |   1 | edu1    |
|    1 | aaa   |   1 | prof2    |   1 | edu1    |
|    1 | aaa   |   1 | prof1    |   1 | edu2    |
|    1 | aaa   |   1 | prof2    |   1 | edu2    |
|    1 | aaa   |   1 | prof1    |   1 | edu3    |
|    1 | aaa   |   1 | prof2    |   1 | edu3    |
+------+-------+-----+----------+-----+---------+

有没有办法在不重复值的情况下获得输出。 感谢

2 个答案:

答案 0 :(得分:2)

这一点猪。

我同意@GordonLinoff,理想情况下,此演示文稿将在客户端完成。

但是,如果我们希望在SQL中执行此操作,那么基本方法是您必须获取每个用户将使用的最大行数(基于每个用户拥有的条目数)职业和教育表,然后是这些计数,最大数量。)

一旦我们获得了每个用户所需的行数,我们就会根据需要使用数字表扩展每个用户的行(我为此目的包含了一个数字生成器)。

然后我们根据联接表中的条目的uid和行号加入每个表,相对于"扩展"的行号。每个用户的行。然后我们选择相关的列,并完成了我们的工作。在出门的路上付钱给护士!

WITH 
number_table(number) AS
(
    SELECT
        (ones.n) + (10 * tens.n) + (100 * hundreds.n) AS number

    FROM --available range 0 to 999
         (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS ones(n)
        ,(VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS tens(n)
        ,(VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS hundreds(n)
)

,users(u_uid, userName) AS
(
    SELECT 1, 'aaa'
    UNION ALL
    SELECT 2, 'bbb'
    UNION ALL
    SELECT 3, 'ccc'
)

,professions(p_u_uid, profName) AS
(
    SELECT 1, 'prof1'
    UNION ALL
    SELECT 1, 'prof2'
    UNION ALL
    SELECT 2, 'prof1'
    UNION ALL
    SELECT 3, 'prof3'
    UNION ALL
    SELECT 3, 'prof2'
)
,educations(e_u_uid, eduName) AS
(
    SELECT 1, 'edu1'
    UNION ALL
    SELECT 1, 'edu2'
    UNION ALL
    SELECT 1, 'edu3'
    UNION ALL
    SELECT 3, 'edu4'
)

,row_counts(uid, row_count) AS
(
    SELECT u_uid, COUNT(u_uid) FROM users GROUP BY u_uid
    UNION ALL
    SELECT p_u_uid, COUNT(p_u_uid) FROM professions GROUP BY p_u_uid
    UNION ALL
    SELECT e_u_uid, COUNT(e_u_uid) FROM educations GROUP BY e_u_uid
)

,max_counts(uid, max_count) AS
(
    SELECT uid, MAX(row_count) FROM row_counts GROUP BY uid
)

SELECT 
    u_uid
    ,userName
    ,p_u_uid
    ,profName
    ,e_u_uid
    ,eduName

FROM
    max_counts 

INNER JOIN 
    number_table ON number BETWEEN 1 AND max_count

LEFT JOIN 
    (
        SELECT u_uid, userName, ROW_NUMBER() OVER (PARTITION BY u_uid ORDER BY userName) AS user_match
        FROM users
    ) AS users
    ON u_uid = uid
    AND number = user_match

LEFT JOIN 
    (
        SELECT p_u_uid, profName, ROW_NUMBER() OVER (PARTITION BY p_u_uid ORDER BY profName) AS prof_match
        FROM professions
    ) AS professions
    ON p_u_uid = uid
    AND number = prof_match

LEFT JOIN 
    (
        SELECT e_u_uid, eduName, ROW_NUMBER() OVER (PARTITION BY e_u_uid ORDER BY eduName) AS edu_match
        FROM educations
    ) AS educations
    ON e_u_uid = uid
    AND number = edu_match

ORDER BY 
     IIF(COALESCE(u_uid, p_u_uid, e_u_uid) IS NULL, 1, 0)   ASC --nulls last
    ,COALESCE(u_uid, p_u_uid, e_u_uid)                      ASC
    ,IIF(COALESCE(p_u_uid, e_u_uid) IS NULL, 1, 0)          ASC --nulls last
    ,COALESCE(p_u_uid, e_u_uid)                             ASC
    ,IIF(e_u_uid IS NULL, 1, 0)                             ASC --nulls last
    ,e_u_uid                                                ASC

结果:

u_uid       userName p_u_uid     profName e_u_uid     eduName
----------- -------- ----------- -------- ----------- -------
1           aaa      1           prof1    1           edu1
NULL        NULL     1           prof2    1           edu2
NULL        NULL     NULL        NULL     1           edu3
2           bbb      2           prof1    NULL        NULL
3           ccc      3           prof2    3           edu4
NULL        NULL     3           prof3    NULL        NULL

答案 1 :(得分:0)

您是否尝试过distinct关键字?

select DISTINCT u.uid ,u.uName,p.uid , p.profName,e.uid,e.eduName
from  user  u inner join profession p on u.uid=p.pid
inner join education e on u.uid = e.uid
where u.uid=p.uid
and u.uid=e.uid
and i.uid=1