Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL联接:选择员工提交的审核状态,以及每年未提交审核的员工列表_Sql_Sql Server_Sql Server 2008_Tsql_Join - Fatal编程技术网

SQL联接:选择员工提交的审核状态,以及每年未提交审核的员工列表

SQL联接:选择员工提交的审核状态,以及每年未提交审核的员工列表,sql,sql-server,sql-server-2008,tsql,join,Sql,Sql Server,Sql Server 2008,Tsql,Join,对于每一年,对于每一位员工,我想列出该员工已提交的审核状态,如果该员工未提交该年的审核,则列出“未启动”状态 用语言表达这个问题有点困难,因此我会尝试通过举例来解释: create table #employees ( empid int, name varchar(100) ) Create table #review ( empid int, ryear int, status varchar(20) ) insert into #review values(1,2016,'S2')

对于每一年,对于每一位员工,我想列出该员工已提交的审核状态,如果该员工未提交该年的审核,则列出“未启动”状态

用语言表达这个问题有点困难,因此我会尝试通过举例来解释:

create table #employees 
(
empid int,
name varchar(100)
)

Create table #review
(
empid int,
ryear int,
status varchar(20)
)

insert into #review values(1,2016,'S2')
insert into #review values(2,2016,'S2')
insert into #review values(2,2017,'S1')
insert into #review values(3,2017,'S2')



insert into #employees values(1,'jack')
insert into #employees values(2,'mack')
insert into #employees values(3,'rack')
insert into #employees values(4,'tack')
错误查询

select a.empid
      ,a.name
      ,b.ryear
      ,case isnull(b.status,'')
           when ''
               then 'Not Initiated'
           else status
       end as status
from #employees as a
    left join #review as b
        on a.empid = b.empid
           and b.ryear in(select distinct
                                 ryear
                          from #review
                         );--something like that
预期结果:

+-------+------+-------+----------------+
| empid | name | ryear |     status     |
+-------+------+-------+----------------+
|     1 | jack |  2016 | S2             |
|     1 | jack |  2017 | not initiated  |
|     2 | mack |  2016 | S2             |
|     2 | mack |  2017 | S1             |
|     3 | rack |  2016 | not initieated |
|     3 | rack |  2017 | S2             |
|     4 | tack |  2016 | Not Initiated  |
|     4 | tack |  2017 | Not Initiated  |
+-------+------+-------+----------------+

您可以在子查询上使用交叉联接

select a.empid
      ,a.name
      ,c.ryear
      ,isnull(b.status,'Not Initiated') as status
from #employees as a
    cross join(select distinct
                      ryear
               from #review
              ) as c
    left join #review as b
            on b.ryear = c.ryear
            and a.empid = b.empid
order by a.empid, ryear

下面是一个使用公共表表达式的示例; 它还支持同一员工在同一年进行多次审核

WITH X AS
(SELECT distinct ryear FROM #review)
SELECT a.empid, a.name, X.ryear, isnull(b.status,'Not initiated')
  FROM X as x
  LEFT
  JOIN #employees as a
    ON 1=1
  LEFT
  JOIN #review as b
    ON a.empid = b.empid
   AND b.ryear = x.ryear
 ORDER 
    BY a.empid,x.ryear

这可能支持同一员工在同一年进行一次以上的审查:

SELECT Employees.empid, Employees.[name], ReviewYears.[Value]
     , [Status] = ISNULL(LatestReviews.[status], 'Not Initiated')
FROM #employees AS Employees
CROSS JOIN (SELECT DISTINCT ryear AS [Value] FROM #review) AS ReviewYears -- We need some source of years, hopefully there are no missing years here.
LEFT JOIN (
    SELECT *
    FROM (
        SELECT empid, ryear, [status]
             , RN = ROW_NUMBER() OVER(PARTITION BY empid, ryear ORDER BY STATUS DESC) -- Per employee and year, we'll take only one status, hopefully we can order by statuses.
        FROM #review
    ) AS T
WHERE RN = 1 -- Refer to comments at creation of RN.
) AS LatestReviews ON LatestReviews.empid = Employees.empid AND LatestReviews.ryear = ReviewYears.[Value] -- Refer to comments at creation of RN.
ORDER BY Employees.empid ASC, ReviewYears.[Value] ASC

用语言表达这个问题有点困难,因此我会尝试通过举例来解释——谢谢,所有问题都应该这样问。@iamdave你是在挖苦人吗?一点也不,你的问题很完美!:)@我是戴夫,这不礼貌,但他有道理。不管怎么说,如果我没记错的话,每年,对于每个员工,你都会列出他提交的审核状态,如果他没有提交,你会列出“未启动”的状态,对吗?没有“order by”语句,结果并不完全符合预期。此外,在子查询SQL上使用交叉连接必须多次获取此数据,因此,使用CTE更有效。事实并非如此,本例中的查询优化程序将子查询和CTE视为相同的。嗨,Simon,我在谷歌上搜索了一下,似乎您对优化器处理子查询和CTE的方式是正确的。但是,需要注意的是,CTE用于使代码更具可读性。如果多次使用,CTE可用于封装查询,在这种简单的情况下,子查询是完全可以接受的。我同意,但对于更复杂的查询,CTE可以帮助使整个语句更具可读性。正如Simon在回答中评论的那样,Hi KtX2SkD使用子查询(以及子查询上的交叉连接),SQL必须多次加载“ryear”数据。通过使用CTE(参见我的答案),只会发生1次提取,因此这对性能更有利。@Karel,谢谢您的评论。我自己对表演几乎一无所知,尽管我试过几次去了解它。我的前辈和工具也几乎没有任何帮助>>事实上,看到Simon对他的答案的评论,再加上谷歌搜索一下,子查询和CTE似乎没有实际的影响,因为SQL优化器会平等地处理这两个问题。然而,值得注意的是,CTE可以使您的SQL更易于阅读。查询可能会给出正确的输出,也可能不是硬编码的,但在现实生活中,我从来没有编写过这样的查询。我会找到一种方法来避免在2列上使用distinct和order by。所以想象一下,在现实生活中,您的查询会有很多变化。