【问题标题】:How to get matching and non matching rows from a SQL Join如何从 SQL Join 中获取匹配和不匹配的行
【发布时间】:2014-06-23 10:03:37
【问题描述】:

我有两个表连接,我想要一个显示所有匹配和不匹配行的结果。在 SQL 中可以吗?

这些是表和查询...

 CREATE TABLE #Day (id int, EID int, PID varchar(10), [Day] int, Shift varchar(10))
 CREATE TABLE #Night (id int, EID int, PID varchar(10), [Day] int, Shift varchar(10))

 INSERT INTO #Day 
 SELECT Atten_ID, EID, PID, DATEPART(DD,in_time) AS [Day], shift
   FROM Attendance
  WHERE (shift = 'D')

 INSERT INTO #Night 
 SELECT Atten_ID, EID, PID, DATEPART(DD,in_time) AS [Day], shift
   FROM Attendance
  WHERE (shift = 'N')

 SELECT #Day.EID, #Day.PID, #Day.Day, #Day.Shift AS DShift, #Night.Shift AS NShift 
   FROM #Day
        JOIN #Night ON #Day.EID = #Night.EID
                   AND #Day.PID = #Night.PID
                   AND #Day.Day = #Night.Day

结果应该是这样的……

EID |  PID  | Day | DShift   | NShift
______________________________________
100 |  S001 |  01 |  D       |   N
100 |  S001 |  02 |  D       |   -
100 |  S001 |  03 |  -       |   N

【问题讨论】:

标签: c# sql .net sql-server join


【解决方案1】:

也许使用 FULL OUTER JOIN

 SELECT COALESCE(d.EID,n.EID),
        COALESCE(d.PID,n.PID),
        COALESCE(d.Day,n.Day),
        d.Shift AS DShift,
        n.Shift AS NShift 
   FROM #Day d
        FULL JOIN #Night n ON d.EID = n.EID AND d.PID = n.PID AND d.Day = n.Day

【讨论】:

  • 谢谢,但出现错误提示:无法绑定多部分标识符“#Day.Shift”。这是什么问题?
  • @Deva:表名有别名,用d.Shift代替#Day.Shift
【解决方案2】:

除了 Sheen 的回答之外,仅作几点说明:

left join 将显示左表中的所有行,以及右表中的匹配行。

full join 将显示两个表中的所有行。

A Visual Explanation of SQL Joins

在回复您的评论时,您可以使用case。这允许您在不同的条件下返回不同的值:

select  ...
,       case 
        when d.Shift is not null and n.Shift is not null then 'D/N'
        when d.Shift is not null then 'D'
        when d.Shift is not null then 'N'
        else '-'
        end as NorD

【讨论】:

  • 只有一件事,如果我需要连接两个移位列,该怎么做? (如果员工两个班次都工作,则应显示为“D/N”)谢谢
【解决方案3】:

实际上,您不需要临时表,只需要 CTE。而且,您可以使用 CASE 来实现D/N 结果:

 WITH vDAY as ( SELECT Atten_ID, EID, PID, DATEPART(DD,in_time) AS [Day], shift
   FROM Attendance
  WHERE (shift = 'D')
 ),
 vNIGHT as (
 SELECT Atten_ID, EID, PID, DATEPART(DD,in_time) AS [Day], shift
   FROM Attendance
  WHERE (shift = 'N')
 )
 SELECT COALESCE(d.EID,n.EID),
    COALESCE(d.PID,n.PID),
    COALESCE(d.Day,n.Day),
    CASE 
      WHEN d.Shift='D' and n.Shift='N' 
        then 'D/N'
      WHEN d.Shift IS NOT NULL then d.Shift
      ELSE COALESCE( d.Shift, '-' ) END
       AS DShift,
    CASE WHEN d.Shift='D' and n.Shift='N'
       then 'D/N' else COALESCE( n.Shift, '-' ) end
       AS NShift 
 FROM vDay d
    FULL JOIN vNight n ON 
       d.EID = n.EID AND d.PID = n.PID AND d.Day = n.Day

【讨论】:

  • 谢谢,但这里有一个问题,如果它不是 D/N,它会给出空值。我正在努力完成这项工作。
  • 您可以在此处发布一些输出,以便我更正查询。或者您可以扩展我的case 语句以获得必要的结果。
  • 最后,移位列中的值应类似于“D”、“N”或“D/N”。但是这个查询结果是'D/N','N'。没有显示“D”,而是显示“-”。是的,我们必须调查 CASE
  • 尝试修改查询,看起来像一些大写/小写问题。 NOT NULL 是一种更常见的情况,应该工作几天
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 2019-12-29
相关资源
最近更新 更多