选择具有JOIN的字段,其中列存在于具有较少字段的不同子查询中

时间:2012-04-04 16:04:27

标签: sql sql-server join

这个问题可能已经被问过,但我似乎无法找到答案,所以这里有:

我从两张桌子上的JOIN中选择了10个字段。结果是大约1186行数据。在这些行中,除了一个唯一字段(ClassId)之外,有几个是重复的,用于所有意图和目的。我需要这个领域,但这让我无法获得和我所定义的“独特”。例如,仅查询CodeTeacherDescripTerm会产生1120条记录。

我希望运行同样的查询,但是添加一个WHERE子句,其子查询搜索一组较窄的字段,上面列出的三个字段是准确的,排除了导致我的那个唯一字段“重复”。当然,我收到的错误如下:

  

“当选择列表中只能指定一个表达式   EXISTS没有引入子查询。“

当我尝试使用EXISTS代替ClassScedule.Code IN时,我仍然回到了完整的1186.

这是我的查询:

 SELECT DISTINCT ClassId
      ,Code
      ,Section
      ,Course
      ,Students
      ,ClassStart
      ,TeacherDescrip
      ,AdTeacherID
      ,email
      ,Term
      ,Campus
  FROM ClassScedule
  JOIN staff ON staff.StaffID = ClassScedule.AdTeacherID
  WHERE ClassStart BETWEEN '2012-03-01' AND '2012-03-30'
        AND ClassScedule.Code IN 
              (SELECT DISTINCT ClassScedule.Code, TeacherDescrip, Termcode 
               FROM ClassScedule 
              WHERE ClassStart BETWEEN '2012-03-01' AND '2012-03-30')
        AND TeacherDescrip IS NOT NULL 
  ORDER BY Instructor

4 个答案:

答案 0 :(得分:1)

如果您使用的是SQL Server 2005或更高版本,则可以为每个不同的(Code,TeacherDescrip,Term)选择一个结果,如下所示:

SELECT TOP (1) WITH TIES
       ClassId
      ,Code
      ,Section
      ,Course
      ,Students
      ,ClassStart
      ,TeacherDescrip
      ,AdTeacherID
      ,email
      ,Term
      ,Campus
  FROM ClassScedule
  JOIN staff ON staff.StaffID = ClassScedule.AdTeacherID
  WHERE ClassStart BETWEEN '2012-03-01' AND '2012-03-30'
  AND TeacherDescrip IS NOT NULL 
  ORDER BY ROW_NUMBER() OVER (
    PARTITION BY Code, TeacherDescrip, Term
    ORDER BY ClassID DESC
  )

在重复(Code,TeacherDescrip,Term)值中,此查询为您提供具有最小ClassID的结果。如果您想要最大的,请删除DESC。

答案 1 :(得分:0)

嗯,肮脏的解决方案是:

 SELECT max(ClassId),
      ,Code ,Section ,Course ,Students ,ClassStart ,TeacherDescrip ,AdTeacherID
      ,email ,Term ,Campus
  FROM ClassScedule
  JOIN staff ON staff.StaffID = ClassScedule.AdTeacherID
  WHERE ClassStart BETWEEN '2012-03-01' AND '2012-03-30'
    AND TeacherDescrip IS NOT NULL 
  GROUP BY Code ,Section ,Course ,Students ,ClassStart ,TeacherDescrip
   ,AdTeacherID ,email ,Term ,Campus
  ORDER BY Instructor

这将为您提供“重复”值的最大ClassId。看起来子查询实际上是获取这些日期之间的所有类代码,但外部查询已经获取所有这些类代码,因此没有必要。

答案 2 :(得分:0)

首先,您不能在子查询中返回多个列来在WHERE子句中进行比较

              ClassScedule.Code IN 
              (SELECT DISTINCT ClassScedule.Code, TeacherDescrip, Termcode 
               FROM ClassScedule 
              WHERE ClassStart BETWEEN '2012-03-01' AND '2012-03-30')

无论如何你都没有帮助,因为你已经从主要的clause

获得了这个

由于该表针对您定义为“唯一”的内容有多个ClassId,因此唯一不会返回多行的方法是从ClassId中删除SELECT。否则,SQL Server无法知道您想要哪个ClassId

如果您只想要一个ClassId,则可以使用MINMAX ClassId并对其他所有内容进行分组。

答案 3 :(得分:0)

通过以下方式将其变成一个大组:

SELECT DISTINCT
      min(ClassId) ClassId
     ,Code
     ,Section
     ,Course 
     ,Students
     ,ClassStart
     ,TeacherDescrip
     ,AdTeacherID
     ,email
     ,Term
     ,Campus
FROM ClassScedule
JOIN staff ON staff.StaffID = ClassScedule.AdTeacherID
WHERE ClassStart BETWEEN '2012-03-01' AND '2012-03-30'
  AND TeacherDescrip IS NOT NULL
GROUP BY
      Code
     ,Section
     ,Course 
     ,Students
     ,ClassStart
     ,TeacherDescrip
     ,AdTeacherID
     ,email
     ,Term
     ,Campus
ORDER BY Instructor

不需要子查询。这些列可能需要稍微调整一下,没有表别名就无法告诉它们来自哪个表。我选择了“第一个”ClassId,但你可以使用max()来取出“最后一个”。