我在 SQL Server 2016 中有一个名为的表df
:
-- Create a new table with department and gender columns
CREATE TABLE df
(
country VARCHAR(50),
year INT,
val1 INT,
val2 INT,
val3 INT,
department VARCHAR(50),
gender VARCHAR(10)
);
-- Insert data into the new table, including department and gender
INSERT INTO df (country, year, val1, val2, val3, department, gender)
VALUES ('USA', 2020, 4, 4, 5, 'Sales', 'Male'),
('USA', 2020, 4, 4, 5, 'Sales', 'Male'),
('USA', 2020, 5, 5, 5, 'Sales', 'Female'),
('USA', 2020, 5, 5, 5, 'Sales', 'Female'),
('USA', 2020, 1, 1, 5, 'Sales', 'Male'),
('USA', 2020, 3, 3, 5, 'Sales', 'Female'),
('USA', 2020, 4, 2, 5, 'Sales', 'Male'),
('USA', 2020, 1, 1, 5, 'Sales', 'Female'),
('USA', 2020, 2, 2, 5, 'Sales', 'Male'),
('Canada', 2020, 2, 2, 3, 'HR', 'Female'),
('Canada', 2020, 2, 2, 3, 'HR', 'Female'),
('Canada', 2020, 2, 2, 3, 'HR', 'Male'),
('Canada', 2020, 2, 2, 3, 'HR', 'Male'),
('Canada', 2020, 5, 5, 3, 'HR', 'Female'),
('Canada', 2020, 5, 5, 3, 'HR', 'Male'),
('Canada', 2020, 1, 1, 3, 'HR', 'Female'),
('Canada', 2020, 1, 1, 3, 'HR', 'Male'),
('Canada', 2020, 3, 4, 3, 'HR', 'Female'),
('Canada', 2020, 3, 4, 3, 'HR', 'Male'),
('Canada', 2020, 5, 4, 3, 'HR', 'Female'),
('Canada', 2020, 5, 4, 5, 'HR', 'Male'),
('Canada', 2020, 5, 4, 5, 'HR', 'Female'),
('Germany', 2022, 5, 5, 4, 'IT', 'Male'),
('France', 2020, 1, 1, 2, 'Finance', 'Female'),
('France', 2020, 1, 1, 2, 'Finance', 'Female'),
('France', 2020, 3, 2, 2, 'Finance', 'Male'),
('France', 2020, 3, 4, 2, 'Finance', 'Female'),
('France', 2020, 3, 5, 5, 'Finance', 'Male'),
('France', 2020, 3, 4, 4, 'Finance', 'Female'),
('France', 2020, 3, 4, 4, 'Finance', 'Male'),
('France', 2020, 3, 4, 3, 'Finance', 'Female'),
('UK', 2021, 4, 2, 3, 'Marketing', 'Male'),
('Australia', 2022, 3, 3, 4, 'Support', 'Female'),
('Italy', 2020, 5, 5, 5, 'Operations', 'Male'),
('Italy', 2020, 5, 5, 5, 'Operations', 'Female'),
('Italy', 2020, 5, 1, 1, 'Operations', 'Male'),
('Italy', 2020, 4, 4, 1, 'Operations', 'Female'),
('Italy', 2020, 2, 1, 2, 'Operations', 'Male'),
('Italy', 2020, 3, 5, 3, 'Operations', 'Female'),
('Spain', 2021, 1, 2, 3, 'Customer Service', 'Male'),
('Mexico', 2022, 4, 4, 4, 'Logistics', 'Female'),
('Brazil', 2020, 4, 1, 1, 'R&D', 'Male'),
('Brazil', 2020, 4, 1, 1, 'R&D', 'Female'),
('Brazil', 2020, 4, 3, 4, 'R&D', 'Male'),
('Brazil', 2020, 5, 3, 5, 'R&D', 'Female'),
('Brazil', 2020, 5, 3, 5, 'R&D', 'Male'),
('Brazil', 2020, 3, 3, 1, 'R&D', 'Female'),
('Brazil', 2020, 2, 3, 1, 'R&D', 'Male');
-- Select all rows from the new table to check the data
SELECT * FROM df;
通过此表,我根据一些过滤创建了一些百分比和计数列。
-- Parameters
DECLARE @Year INT = 2020;
DECLARE @Metric VARCHAR(50) = 'count';
DECLARE @Gender VARCHAR(20) = NULL; -- Set to specific gender (e.g., 'Male', 'Female') or NULL to include all
DECLARE @Department VARCHAR(50) = NULL; -- Set to specific department (e.g., 'HR', 'Engineering') or NULL to include all
-- Set @Metric to 'dissatisfaction', 'satisfaction', or 'count'
WITH UnpivotedData AS
(
SELECT country, gender, department, year, Vals
FROM
(SELECT country, gender, department, year, val1, val2, val3
FROM df) AS SourceTable
UNPIVOT
(Vals FOR ValueColumn IN (val1, val2, val3)) AS Unpivoted
WHERE year = @Year
),
Proportions AS
(
SELECT
country,
gender,
department,
CASE
WHEN Vals = 1 THEN 'Very Dissatisfied'
WHEN Vals = 2 THEN 'Dissatisfied'
WHEN Vals = 3 THEN 'Neutral'
WHEN Vals = 4 THEN 'Satisfied'
WHEN Vals = 5 THEN 'Very Satisfied'
END AS SatisfactionLevel,
COUNT(*) * 1.0 / SUM(COUNT(*)) OVER (PARTITION BY country, gender, department) AS Proportion
FROM
UnpivotedData
GROUP BY
country, gender, department, Vals
),
Pivoted AS
(
SELECT country, gender, department,
[Very Dissatisfied],
[Dissatisfied],
[Neutral],
[Satisfied],
[Very Satisfied]
FROM Proportions
PIVOT
(MAX(Proportion)
FOR SatisfactionLevel IN ([Very Dissatisfied], [Dissatisfied], [Neutral], [Satisfied], [Very Satisfied])) AS p
),
CountryCounts AS
(
SELECT
CASE WHEN country IS NULL THEN 'Unknown' ELSE country END AS country,
gender,
department,
COUNT(*) AS Total
FROM df
WHERE year = @Year
-- Apply filters for gender and department if provided
AND (@Gender IS NULL OR gender = @Gender)
AND (@Department IS NULL OR department = @Department)
GROUP BY CASE WHEN country IS NULL THEN 'Unknown' ELSE country END, gender, department
),
OrderedData AS
(
SELECT
p.country,
p.gender,
p.department,
[Very Dissatisfied],
[Dissatisfied],
[Neutral],
[Satisfied],
[Very Satisfied],
c.Total,
CASE
WHEN @Metric = 'satisfaction' THEN ISNULL([Satisfied], 0) + ISNULL([Very Satisfied], 0)
WHEN @Metric = 'dissatisfaction' THEN ISNULL([Very Dissatisfied], 0) + ISNULL([Dissatisfied], 0)
WHEN @Metric = 'count' THEN c.Total
END AS SortValue
FROM Pivoted AS p
INNER JOIN CountryCounts AS c ON p.country = c.country AND p.gender = c.gender AND p.department = c.department
)
SELECT
country,
gender,
department,
[Very Dissatisfied],
[Dissatisfied],
[Neutral],
[Satisfied],
[Very Satisfied],
Total
FROM
OrderedData
ORDER BY
SortValue DESC;
我想创建一个具有 3 个参数的表函数:
- 公制
- 年
- 因素
Factor
可以是性别或部门,或者两者皆可。例如,如果Factor
是性别,则表格按性别分组;如果是部门,则表格按部门分组。
如果两者同时进行分组。如果Factor
为空或默认,则根本不进行分组。
关于Year
:如果Year
传入的是按年份分组,如果Year
是空,则显示所有年份,不进行分组。
有没有办法在 SQL Server 中做到这一点?
我这里有一把小提琴
正如我在您之前的 SQL 问题中告诉您的那样,您把这个问题复杂化了。
您可以在 CTE 的单个级别中执行过滤、取消透视和透视,并且只需要一个级别来添加
Total
,如果有一个列,这本身就没有必要ID
,因为您可以执行COUNT(DISTINCT ID)
。要创建函数,只需添加常规
CREATE FUNCTION
语法。您不能ORDER BY
向表添加函数,它基本上只是一个视图。您需要将其添加到外部查询中。然后你就做
db<>小提琴
请注意,sort-value 参数不应从变量或横向连接传入,因为这会大大降低查询速度。如果它是常量字符串,那么优化器可以将其排除在外。
Adding in dynamic grouping substantially complicates this, because now you need to null out the values before you group them up (as shown in the other answer). It will also be really slow on large tables, as you can't use indexes. I would strongly recommend you create separate functions with different grouping/partitioning constructs, alternatively do this in dynamic SQL.
我们正在对要分组的列应用值替换。例如,如果参数 @factorGender 为空,则我们按值分组,
gender
否则按常量值分组all
- 事实上,不按性别分组。为了简化问题,子查询相当于你的 UNPIVOT-PIVOT 操作。我们可以直接计算 val1、val2、val3 的值分散度。表达式
或
对所有行计数 val1=1、val2=1、val3=1。
查看示例
更新 1。在 @DaleK 评论之后,我决定我确实需要更准确地回答这个问题,并提出一个函数示例和一个其使用示例。
并调用此函数
输出为
因此,尝试使用另一组条件运行查询。
小提琴
如果您的服务器上没有可用的函数,
IIF(...)
请使用以下命令转换此表达式case when ... end
小提琴
和