如何使两列和其他列正常旋转

时间:2018-12-04 16:45:40

标签: sql-server sql-server-2008

我有3个表格,分别是class,Student和Religion,以下数据如下

分类表

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 :(得分:1)

这是更关键的条件聚合。这样可以为您带来想要的结果:

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现在已经指出,除了所提供的两种宗教之外,还有更多的宗教,并且需要保持动态。因此,得出:

--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;

答案 1 :(得分:1)

这是带有动态列的数据透视表。您的宗教信仰数目不详

// Using native promises:
const calculateExpense = function (proName) {
    return fetch('/purchase')
        .then((response) => {
            if (response.status >= 400) { throw new Error(response.status.toString()); }

            const result = response.json();

            let totalExpense = 0;
            let totalQuantity = 0;

            for (let purchase of result) {
                if (proName === purchase.productName) {
                    totalExpense += purchase.totalPrice;
                    totalQuantity += purchase.purchasedQuantity;
                }
            }

            return totalExpense / totalQuantity;
        });
};

// Using async/await:
const calculateExpense = async function (proName) {
    const response = await fetch('/purchase');

    if (response.status >= 400) { throw new Error(response.status.toString()); }

    const result = response.json();

    let totalExpense = 0;
    let totalQuantity = 0;

    for (let purchase of result) {
        if (proName === purchase.productName) {
            totalExpense += purchase.totalPrice;
            totalQuantity += purchase.purchasedQuantity;
        }
    }

    return totalExpense / totalQuantity;
};

calculateExpense('name')
    .then((expensePerProduct) => {
        // TODO: do something.
    })
    .catch(err => console.log(`Error: ${err}`));