Как сделать две колонки опорными, а другие как обычно - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть 3 таблицы названия класса, ученик и религия, и ниже приведены данные

Таблица класса

ClassId     ClassName
  1         class-1
  2         class-2
  3         class-3

Таблица религии

ReligionId    RegionName
  1           Hindu
  2           Muslim

Таблица учеников

employeeid  StudentName religionid  dateofbirth classid
    1         A               1     1990-12-04    1
    2         B               2     1999-12-04    2
    3         C               2     2000-12-04    1
    4         D               2     1988-12-04    1
    5         E               2     2003-12-04    2
    6         F             NULL    2002-12-04    1

Как можно добиться записи из приведенных выше таблиц ниже

CLASSNAME  HINDU   MUSLIM  Noreligion
  class-1     1     2           1
  class-2     0     2           0

Вы можете создавать таблицы изприведенные ниже сценарии

CREATE TABLE [dbo].[class](
    [ClassId] [int] IDENTITY(1,1) NOT NULL,
    [ClassName] [varchar](250) NULL,
 CONSTRAINT [PK_class] PRIMARY KEY CLUSTERED 
(
    [ClassId] 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

CREATE TABLE [dbo].[Religion](
    [ReligionId] [int] NOT NULL,
    [RegionName] [varchar](50) NULL,
 CONSTRAINT [PK_Religion] PRIMARY KEY CLUSTERED 
(
    [ReligionId] 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

CREATE TABLE [dbo].[Student](
    [employeeid] [int] IDENTITY(1,1) NOT NULL,
    [StudentName] [varchar](150) NULL,
    [religionid] [int] NULL,
    [dateofbirth] [date] NULL,
    [classid] [int] NULL,
 CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED 
(
    [employeeid] 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
SET IDENTITY_INSERT [dbo].[class] ON 

INSERT [dbo].[class] ([ClassId], [ClassName]) VALUES (1, N'class-1')
INSERT [dbo].[class] ([ClassId], [ClassName]) VALUES (2, N'class-2')
INSERT [dbo].[class] ([ClassId], [ClassName]) VALUES (3, N'class-3')
SET IDENTITY_INSERT [dbo].[class] OFF
INSERT [dbo].[Religion] ([ReligionId], [RegionName]) VALUES (1, N'hindu')
INSERT [dbo].[Religion] ([ReligionId], [RegionName]) VALUES (2, N'muslim')
SET IDENTITY_INSERT [dbo].[Student] ON 

INSERT [dbo].[Student] ([employeeid], [StudentName], [religionid], [dateofbirth], [classid]) VALUES (1, N'A', 1, CAST(N'1990-12-04' AS Date), 1)
INSERT [dbo].[Student] ([employeeid], [StudentName], [religionid], [dateofbirth], [classid]) VALUES (2, N'B', 2, CAST(N'1999-12-04' AS Date), 2)
INSERT [dbo].[Student] ([employeeid], [StudentName], [religionid], [dateofbirth], [classid]) VALUES (3, N'C', 2, CAST(N'2000-12-04' AS Date), 1)
INSERT [dbo].[Student] ([employeeid], [StudentName], [religionid], [dateofbirth], [classid]) VALUES (4, N'D', 2, CAST(N'1988-12-04' AS Date), 1)
INSERT [dbo].[Student] ([employeeid], [StudentName], [religionid], [dateofbirth], [classid]) VALUES (5, N'E', 2, CAST(N'2003-12-04' AS Date), 2)
INSERT [dbo].[Student] ([employeeid], [StudentName], [religionid], [dateofbirth], [classid]) VALUES (6, N'F', NULL, CAST(N'2002-12-04' AS Date), 1)
SET IDENTITY_INSERT [dbo].[Student] OFF

Требуется ли для этого использование сводной таблицы.Я не смог выполнить запрос, получив такие записи.

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Это сводная таблица с динамическими столбцами.Вы можете иметь неизвестное количество религий

DECLARE @cols AS NVARCHAR(MAX), @sql  AS NVARCHAR(MAX);    

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(ReligionName) 
            FROM Religion c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

Set @sql = '
SELECT  ClassId, '+ @cols + ',[NoReligion] 
FROM
  (
   Select 
     IIf (ReligionName IS NULL, ''NoReligion'', ReligionName) As ReligionName,
     employeeid,s.ClassId 
   From
   Student s INNER JOIN
   Class ON s.classid = Class.ClassId FULL OUTER JOIN
   Religion ON s.religionid = Religion.ReligionId) As src 
   Pivot
(
Count(employeeid) 
FOR ReligionName IN('+@cols+',[NoReligion])
) As pvt'


EXECUTE sp_executesql @sql
0 голосов
/ 04 декабря 2018

Это более условная агрегация, чем сводная.Это дает вам результат, который вы ищете:

SELECT C.ClassName,
       COUNT(CASE R.RegionName WHEN 'Hindu' THEN 1 END) AS Hindu,
       COUNT(CASE R.RegionName WHEN 'Muslim' THEN 1 END) AS Muslim,
       COUNT(CASE WHEN  R.RegionName IS NULL THEN 1 END) AS NoReligion
FROM dbo.class C
     JOIN dbo.Student S ON C.ClassId = S.classid
     LEFT JOIN dbo.Religion R ON S.religionid = R.ReligionId
GROUP BY C.ClassName;

Если вы не понимаете синтаксис, пожалуйста, спросите.

Редактировать: OP уже заявил, что есть большерелигии, а не только 2, которые они предоставили, и должны быть динамичными.Следовательно, это дает:

--Additional sample row if you wish:
INSERT [dbo].[Religion] ([ReligionId], [RegionName])
VALUES (3, N'Catholic');
GO

DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT C.ClassName,' + NCHAR(10) +
           STUFF((SELECT N',' + NCHAR(10) +
                         N'       COUNT(CASE R.RegionName WHEN ' + QUOTENAME(R.RegionName,N'''') + N' THEN 1 END) AS ' + QUOTENAME(R.RegionName)
                  FROM dbo.Religion R
                  ORDER BY R.ReligionId
                  FOR XML PATH(N'')),1,2,N'') + N',' + NCHAR(10) +
           N'COUNT(CASE WHEN  R.RegionName IS NULL THEN 1 END) AS NoReligion' + NCHAR(10) +
           N'FROM dbo.class C' + NCHAR(10) +
           N'     JOIN dbo.Student S ON C.ClassId = S.classid' + NCHAR(10) +
           N'     LEFT JOIN dbo.Religion R ON S.religionid = R.ReligionId' + NCHAR(10) +
           N'GROUP BY C.ClassName;';

SELECT @SQL;
EXEC sp_executesql @SQL;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...