使用SQL显示基于记录计数的结果

时间:2013-09-22 17:30:57

标签: sql sql-server sql-server-2008

我有一个名为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

以下是数据的屏幕截图:

enter image description here

我希望能够找到所有去过名为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

6 个答案:

答案 0 :(得分: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

如果你想要大学的coursename那么你可以在内部查询中返回它。但由于每个大学课程只有一个记录,外部selectgroup 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%'

答案 1 :(得分:2)

一个简单的答案。

  1. 我选择所有感兴趣的行(即“中学”或coursename)。
  2. 我计算每个学生的行数。
  3. 我过滤以保留至少有2行的学生。
  4. 我在ORDER BY中使用了一个表达式,以确保中学首先出现。
  5. 你的问题不明确的是当行数超过2行时会发生什么。在这种情况下,它们都显示出来,但查询很容易调整(在rn&lt; = 2上添加row_number和filter)。

    小提琴: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
    

答案 2 :(得分: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
    )

实际上,如果至少有一行INSTITUTIONNAME = 'Secondary School'且至少有一行INSTITUTIONNAME <> 'Secondary School'

,这两个查询都会显示STUDENTNUMBER的所有行

<强> sql fiddle demo

答案 3 :(得分: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)

答案 4 :(得分: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%'
))

应该有用吗?

答案 5 :(得分: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
             )