4

我有一个名为 schoolDB 的数据库和 2 个数据库表,

studenteducation

创建学生表:

USE [schoolDB]
GO

/****** Object:  Table [dbo].[tblStudent]    Script Date: 09/22/2013 17:30:11 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tblStudent](
    [STUDENTNUMBER] [varchar](50) NOT NULL,
    [STUDENTNAME] [varchar](50) NULL,
    [EDUCATIONID] [varchar](50) NULL,
 CONSTRAINT [PK_tblStudent] PRIMARY KEY CLUSTERED 
(
    [STUDENTNUMBER] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

创建教育表:

USE [schoolDB]
GO

/****** Object:  Table [dbo].[tblEducation]    Script Date: 09/22/2013 17:31:30 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tblEducation](
    [EDUCATIONID] [varchar](50) NOT NULL,
    [STUDENTNUMBER] [varchar](50) NULL,
    [INSTITUTIONNAME] [varchar](50) NULL,
    [COURSENAME] [varchar](50) NULL,
    [GRADE] [varchar](50) NULL,
    [YEAROFLEAVING] [varchar](50) NULL
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

这是数据的截图:

在此处输入图像描述

我希望能够找到每个去过一个名为的机构Secondary School并且有另一个带有课程名称的教育记录的人like biol。不仅限于生物学,我想找到所有的科学,所以我需要放多个类似的陈述。

我试过这个:

SELECT COUNT(*) AS 'Our Students', 
       DTOurStudents.STUDENTNAME 
FROM   (SELECT TOP 2 TBLSTUDENT.STUDENTNUMBER, 
                     TBLSTUDENT.STUDENTNAME, 
                     TBLEDUCATION.INSTITUTIONNAME, 
                     TBLEDUCATION.COURSENAME 
        FROM   TBLEDUCATION 
               INNER JOIN TBLSTUDENT 
                       ON TBLEDUCATION.STUDENTNUMBER = TBLSTUDENT.STUDENTNUMBER 
        WHERE  TBLEDUCATION.INSTITUTIONNAME LIKE '%Secondary School%') 
       DTOurStudents 
GROUP  BY DTOurStudents.STUDENTNAME

SQL FIDDLE: http ://sqlfiddle.com/#!3/666f8/2

4

6 回答 6

3

通过加入机构表,这将为您提供学生列表和大学课程数量(每所大学)。

SELECT
  STUDENTNUMBER,
  SCHOOL_NAME,
  COLLEGE_NAME,
  count(*) as COLLEGE_COURSES
FROM (
  SELECT    
    school.STUDENTNUMBER,
    school.INSTITUTIONNAME AS SCHOOL_NAME,
    college.INSTITUTIONNAME AS COLLEGE_NAME
  FROM dbo.tblEducation as school
  INNER JOIN dbo.tblEducation as college ON school.STUDENTNUMBER = college.STUDENTNUMBER
  WHERE school.INSTITUTIONNAME = 'Secondary School'
    AND college.INSTITUTIONNAME <> 'Secondary School'
    AND (college.COURSENAME like 'biol%'
         OR college.COURSENAME like 'math%'
         OR college.COURSENAME like 'etc%')
) AS c
GROUP BY STUDENTNUMBER, SCHOOL_NAME, COLLEGE_NAME

如果您想要大学课程名称,那么您可以在内部查询中返回它。但是由于每门大学课程只有一个记录,因此外部select和外部group by将是多余的。

SELECT  
  school.STUDENTNUMBER,
  school.INSTITUTIONNAME AS SCHOOL_NAME,
  college.INSTITUTIONNAME AS COLLEGE_NAME,
  college.COURSENAME
FROM dbo.tblEducation as school
INNER JOIN dbo.tblEducation as college ON school.STUDENTNUMBER = college.STUDENTNUMBER
WHERE   school.INSTITUTIONNAME = 'Secondary School'
  AND college.INSTITUTIONNAME <> 'Secondary School'
  AND  (college.COURSENAME like 'biol%'
          OR college.COURSENAME like 'math%'
          OR college.COURSENAME like 'etc%'
于 2013-09-23T02:08:21.967 回答
2

一个简单的答案。

  1. 我选择所有感兴趣的行(即“中学”或按课程名称)。
  2. 我计算每个学生的行数。
  3. 我过滤以保留至少有 2 行的学生。
  4. 我在 中使用了一个表达式ORDER BY来确保中学首先出现。

您的问题不清楚的是当有超过 2 行时应该发生什么。在这种情况下,它们都会显示出来,但是查询很容易调整(添加 row_number 并在 rn <= 2 上进行过滤)。

小提琴:http ://sqlfiddle.com/#!3/666f8/89/0

WITH cte as (
  SELECT  
    STUDENTNUMBER, 
    COURSENAME, 
    INSTITUTIONNAME,
    COUNT(*) OVER (PARTITION BY STUDENTNUMBER) AS RecordCount
  FROM tblEducation
  WHERE INSTITUTIONNAME = 'Secondary School'
     OR COURSENAME like 'biol%'
     OR COURSENAME like 'math%'
     OR COURSENAME like 'etc%'
)
select *
from cte
where RecordCount >= 2
order by 
  studentnumber, 
  case when institutionname = 'Secondary School' then 1 else 2 end

编辑

一条评论正确地指出,查询没有检查至少有一所中学和一所其他教育。可能有两所中学,或者根本没有中学!

这些情况可以通过下面稍微复杂的查询来处理:

WITH cte as (
  SELECT  
    STUDENTNUMBER, 
    COURSENAME, 
    INSTITUTIONNAME,
    SUM(CASE INSTITUTIONNAME WHEN 'Secondary School' THEN 1 END) 
      OVER (PARTITION BY STUDENTNUMBER) AS SecondarySchoolCount,
    SUM(CASE WHEN INSTITUTIONNAME <> 'Secondary School' 
              AND COURSENAME LIKE 'biol%' 
             THEN 1 END) 
      OVER (PARTITION BY STUDENTNUMBER) AS CourseCount
  FROM tblEducation
  WHERE INSTITUTIONNAME = 'Secondary School'
     OR COURSENAME like 'biol%'
     OR COURSENAME like 'math%'
     OR COURSENAME like 'etc%'
)
select *
from cte
where SecondarySchoolCount >= 1 AND CourseCount >= 1
order by 
  studentnumber, 
  case when institutionname = 'Secondary School' then 1 else 2 end
于 2013-09-26T19:40:16.480 回答
1

尝试这个

WITH CTE AS
(
SELECT E.STUDENTNUMBER
FROM (SELECT * FROM TBLEDUCATION WHERE INSTITUTIONNAME LIKE '%Secondary School%') E
INNER JOIN (SELECT * FROM TBLEDUCATION WHERE  INSTITUTIONNAME NOT LIKE '%Secondary School%' AND COURSENAME LIKE '%biol%') E1
ON E.STUDENTNUMBER=E1.STUDENTNUMBER
)

SELECT *
FROM   TBLSTUDENT S
INNER JOIN TBLEDUCATION E
ON S.STUDENTNUMBER = E.STUDENTNUMBER
WHERE S.STUDENTNUMBER IN (SELECT STUDENTNUMBER FROM CTE)
于 2013-09-25T08:07:47.223 回答
1
SELECT DISTINCT s.STUDENTNUMBER
FROM tblStudent s
INNER JOIN tblEducation e
ON (s.studentnumber = e.studentnumber and (
    e.institutionname = 'Secondary School'
    or e.coursename like '%biol%' 
    OR e.coursename like '%math%'
))

应该管用?

于 2013-09-25T08:51:49.587 回答
1

以下示例在关联子查询上使用 EXISTS 运算符,该子查询具有连接两个查询

SELECT *
FROM dbo.tblEducation t
WHERE EXISTS (SELECT 1
              FROM (SELECT e.STUDENTNUMBER
                    FROM dbo.tblEducation e
                    WHERE e.INSTITUTIONNAME = 'Secondary School'
              ) x JOIN (SELECT e2.STUDENTNUMBER 
                        FROM dbo.tblEducation e2
                        WHERE e2.INSTITUTIONNAME != 'Secondary School'
                        ) x2 ON x.STUDENTNUMBER = x2.STUDENTNUMBER
              WHERE x.STUDENTNUMBER =  t.STUDENTNUMBER
              )

见演示SQLFiddle

或者

SELECT *
FROM tblEducation t3
WHERE EXISTS(SELECT t.STUDENTNUMBER
             FROM tblEducation t
             WHERE t.INSTITUTIONNAME LIKE 'Secondary School'
               AND EXISTS(SELECT 1
                          FROM tblEducation t2
                          WHERE t.STUDENTNUMBER = t2.STUDENTNUMBER
                            AND t2.INSTITUTIONNAME != t.INSTITUTIONNAME
                          )
               AND t3.STUDENTNUMBER = t.STUDENTNUMBER
             )
于 2013-09-26T10:31:34.033 回答
1

如果您希望两行都显示,可以使用以下查询:

select a.*    
from tblEducation as a
where
    exists (
        select *  
        from tblEducation as t
        where t.INSTITUTIONNAME = 'Secondary School' and t.STUDENTNUMBER = a.STUDENTNUMBER  
    ) and
    exists (
        select *
        from tblEducation as t
        where t.INSTITUTIONNAME <> 'Secondary School' and t.STUDENTNUMBER = a.STUDENTNUMBER  
    )

或者你可以这样做:

with cte as (
    select
        a.STUDENTNUMBER
    from tblEducation as a
    group by
        a.STUDENTNUMBER,
        case when a.INSTITUTIONNAME = 'Secondary School' then 1 else 0 end
)
select a.*
from tblEducation as a
where
    a.STUDENTNUMBER in (
         select t.STUDENTNUMBER
         from cte as t group by t.STUDENTNUMBER
         having count(*) > 1
    )

实际上,这两个查询都显示 STUDENTNUMBER 的所有行,如果存在至少一行INSTITUTIONNAME = 'Secondary School'和至少一行INSTITUTIONNAME <> 'Secondary School'

sql fiddle demo

于 2013-09-25T07:01:34.157 回答