SQL:多个SELECT而不是JOIN

时间:2017-03-14 16:45:09

标签: sql-server join union

我对SQL并不是全新的,但这次我的速度很慢。 对于数据导出,我必须选择一些用户数据,包括两个JOIN。数据不相关,我只需要在一个出口表中同时提供这两种信息。

我创建了一个例子。 groupname 列来自一个JOIN,另一个JOIN列 course

╔════╦═══════════╦══════════╦═══════════╦════════════╗
║ id ║ firstname ║ lastname ║ groupname ║   course   ║
╠════╬═══════════╬══════════╬═══════════╬════════════╣
║  1 ║ John      ║ Doe      ║ Manager   ║ Management ║
║  1 ║ John      ║ Doe      ║ CEO       ║ Management ║
║  1 ║ John      ║ Doe      ║ Manager   ║ Logistics  ║
║  1 ║ John      ║ Doe      ║ CEO       ║ Logistics  ║
║  1 ║ John      ║ Doe      ║ Manager   ║ Leadership ║
║  1 ║ John      ║ Doe      ║ CEO       ║ Leadership ║
╚════╩═══════════╩══════════╩═══════════╩════════════╝

由于JOINS的性质; groupname-column现在多次重复。但我真正想要的是这样的事情:

╔════╦═══════════╦══════════╦═══════════╦════════════╗
║ id ║ firstname ║ lastname ║ groupname ║   course   ║
╠════╬═══════════╬══════════╬═══════════╬════════════╣
║  1 ║ John      ║ Doe      ║ Manager   ║            ║
║  1 ║ John      ║ Doe      ║ CEO       ║            ║
║  1 ║ John      ║ Doe      ║           ║ Management ║
║  1 ║ John      ║ Doe      ║           ║ Logistics  ║
║  1 ║ John      ║ Doe      ║           ║ Leadership ║
╚════╩═══════════╩══════════╩═══════════╩════════════╝

我猜,连续做两个SELECT语句会是更好的选择。不幸的是,原始查询与JOINS和where-Arguments有25行代码,所以我不想复制它。 有没有办法更容易实现我的输出方式然后做一个带有两个长查询的UNION(在这种情况下见下面的简单示例)?

SELECT u.[id]
      ,[firstname]
      ,[lastname]
      ,groupname
      ,'' AS course
  FROM [dbo].[users] u
  JOIN dbo.groups g ON u.id = g.userId
UNION ALL
SELECT u.[id]
      ,[firstname]
      ,[lastname]
      ,'' AS groupname
      ,course
  FROM [dbo].[users] u
  JOIN dbo.courses c ON u.id = c.userId 

2 个答案:

答案 0 :(得分:1)

您可以使用相关查询创建一个表值UDF,然后使用两个UDF创建一个UNION ALL

<强>临
- 更短的查询:

SELECT * FROM [MY_UDF](Param 1, Param 2, ...)<br/>
UNION ALL<br/>
SELECT * FROM [MY_UDF](Different Param 1, Different Param 2, ...)

<强>缺点:
- 您必须创建值为UDF的表。

否则:我认为QUERY_1 UNION ALL QUERY_2可能是要走的路。

答案 1 :(得分:0)

我认为他们有很多方法可以解决你的问题。我会给你最好的想法。

第一个解决方案:只需使用WITH不要重复您的公共部分查询,如下所示:

WITH CommonPart (id, firstname, lastname)
AS
(
    Select id, firstname, lastname
    From [dbo].[users]
    -- Eventually a filter ...
)

SELECT cp.*
  , g.groupname
  , '' AS course
FROM CommonPart cp
JOIN dbo.groups g ON cp.id = g.userId
UNION ALL
SELECT cp.*
  ,'' AS groupname
  ,c.course
FROM CommonPart cp
JOIN dbo.courses c ON cp.id = c.userId 

第二个解决方案:您可以将空值插入coursesgroups并使用简单的LEFT JOIN。但我不喜欢第二种解决方案。

编辑:插入空值后,它看起来像:

Select  u.id,
        u.firstname,
        u.lastname,
        g.groupname,
        c.course
From [dbo].[users] u
Left Join [dbo].[groups] g ON g.userId = u.id
Left Join [dbo].[courses] c ON c.userId = u.id
Where (g.groupname IS NULL and c.course IS NOT NULL) 
  OR  (g.groupname IS NOT NULL and c.course IS NULL)