2013-09-22 2 views
4

У меня есть база данных с именем schoolDB и 2 таблицы базы данных,Отображение результатов, основанных на количество записей с помощью SQL

student и education

Создать студенческий стол:

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 И кто имеет другую запись образования с названием курса likebiol. Не ограничиваясь только биологией, я хочу найти все науки, поэтому мне нужно поставить несколько подобных утверждений.

Я попытался это:

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 скрипку:http://sqlfiddle.com/#!3/666f8/2

+0

Что такое ПК в 'tblEducation'? –

+0

Почему ваш заголовок упоминается? –

+0

Первичный ключ таблицы образования - образованиеID. – PriceCheaperton

ответ

2

Простой ответ.

  1. Я выбираю все интересующие строки (т. Е. «Средняя школа» или по courseame).
  2. Я подсчитываю количество строк на одного учащегося.
  3. Я фильтрую, чтобы удержать учащихся, у которых есть как минимум 2 строки.
  4. Я использую выражение в ORDER BY, чтобы убедиться, что средняя школа появляется в первую очередь.

Вопрос о том, что ваш вопрос остается неясным, - это то, что должно произойти, когда имеется более двух строк. В этом случае все они появляются, но запрос достаточно прост для настройки (добавьте row_number и фильтр по rn < = 2).

Fiddle: 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 

EDIT

Комментарий правильно указывает, что запрос не проверяет, что существует по крайней мере одна средняя школа и один другое образование. Там могут быть две средние школы или вообще нет средней школы!

Эти случаи могут быть обработаны с чуть более сложным запросом ниже:

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 
+0

+1 не знаю, как я пропустил, используя функции windows здесь :( –

+0

Что произойдет, если у одного из учеников будет только одно название учреждения под названием «Средняя школа», но с разными курсами? –

+0

@AlexanderFedorenko. конечно, есть 2 строки, но он не гарантирует, что есть хотя бы одна средняя школа, а также что есть что-то еще, чем в средних школах. Исправить это, я бы заменил COUNT (*) на один «SecondarySchoolCount» и 'CourseCount', и вместо проверки' RecourdCount> = 2' вы можете проверить «SecondarySchoolCount> = 1 и CourseCount> = 1'. – jods

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 

Если вы хотите получить колледж courseame, то вы можете вернуть его во внутреннем запросе. Но так как в колледже есть только одна запись, внешние 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%' 
+0

Это не работает для меня .... любой шанс на скрипку? – PriceCheaperton

+0

Не запускается или не дает желаемых результатов? Какую ошибку/результаты вы получите? – david25272

+0

Это просто показывает среднюю школу. Я не думаю, что «<>» фактически работает. – PriceCheaperton

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 
    ) 

Собственно оба этих запросов Diplay все строки для STUDENTNUMBER, если существует хотя бы одна строка с INSTITUTIONNAME = 'Secondary School' и по меньшей мере одна строка с INSTITUTIONNAME <> 'Secondary School'

sql fiddle demo

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) 
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%' 
)) 

Должен работать?

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 
      ) 
Смежные вопросы