经过大量搜索网络和Stackoverflow后,仍在寻找一种方法来使用ALIAS返回列而不产生新的行/行。
以下工作创建列“Sig_1_Emp”和“Sig_3_Staff”,但Sig_1_Emp和Sig_3_Staff的数据不在同一行,而是两行。
CASE
WHEN VisitSignatures.order = 1 THEN Employees.last_name
END AS Sig_1_Emp,
CASE
WHEN VisitSignatures.order = 3 THEN Employees.last_name
END AS Sig_3_Staff
那么,会不会像以后那样工作?
CASE WHEN VisitSignatures.order = 1 THEN Employees.last_name AS Sig_1_Emp
WHEN VisitSignatures.order = 3 THEN Employees.last_name AS Sig_3_Staff
END
以下是完整查询:
Select
CV.clientvisit_id,
CV.program_id,
CV.visittype,
CV.non_billable,
CV.rev_timein,
CASE
WHEN CVSig.ord = 1 THEN Employees.last_name
ELSE Null
END AS Sig_1_Emp,
CASE
WHEN CVSig.ord = 3 THEN Employees.last_name
ELSE Null
END AS Sig_3_Staff
From CV
Inner Join CVSig On CV.clientvisit_id = CVSig.clientvisit_id
Inner Join EmpSig On CVSig.employeesignature_id = EmpSig.employeesignature_id
Inner Join Employees On EmpSig.emp_id = Employees.emp_id
Where
CV.program_id In (121, 123)
And CV.rev_timein >= @param1
And CV.rev_timein <= DATEADD(d, 1, @param2)
结果样本:
+----------------+------------+-----------+------------+-----------+-------------+
| clientvisit_id | program_id | visittype | rev_timein | sig_1_emp | sig_3_staff |
+----------------+------------+-----------+------------+-----------+-------------+
| 1001 | 121 | M_Mgmnt | 7/1/2014 | | Nurse_Pat |
| 1001 | 121 | M_Mgmnt | 7/1/2014 | Doc_Sue | |
+----------------+------------+-----------+------------+-----------+-------------+
这就是我希望实现的目标:
+----------------+------------+-----------+------------+-----------+-------------+
| clientvisit_id | program_id | visittype | rev_timein | sig_1_emp | sig_3_staff |
+----------------+------------+-----------+------------+-----------+-------------+
| 1001 | 121 | M_Mgmnt | 7/1/2014 | Doc_Sue | Nurse_Pat |
+----------------+------------+-----------+------------+-----------+-------------+
我为这种困惑道歉,并感谢您的耐心等待。 如果这不能澄清我的问题,请删除此帖子。
答案 0 :(得分:2)
如果我正确理解您的问题,您可以尝试pivot
您的结果。您可以将max
聚合与case
语句一起使用来执行此操作:
select
otherfields,
max(CASE WHEN VisitSignatures.order = 1
THEN Employees.last_name END) AS Sig_1_Emp,
max(CASE WHEN VisitSignatures.order = 3
THEN Employees.last_name END) AS Sig_3_Staff
from tables (VisitSignatures and Employees and others)
group by otherfields
无论您选择哪个其他字段,您都希望包含在group by
条款中。
答案 1 :(得分:0)
寻找一种方法来使用ALIAS返回列而不产生新的行/行
您表达这个问题的方式是一个红旗,表示您可能无法理解有关数据库形式和功能的一些重要事项。
严格来说,SELECT
查询会返回一个具有固有结构的结果集,与其显示方式无关。所以查询不会产生&#34;新行或新行,如果您按照这些条款考虑结果,您将经常遇到这种麻烦。我不打算在这里详细介绍,但我强烈建议您阅读关于关系模型和基于集合的思考。
你想在这里做两件不同的事情:
Sig_1_Emp
和Sig_1_Staff
)的多个属性选择值,仅基于表格的一个属性(VisitSignatures.order
) 。 CASE
表达式 1 并非真正设计为独立完成其中任何一项;它只是当你需要一个条件逻辑用于单个列时使用的表达式。您不能跨多个列使用函数或表达式。但是,您可以为每个子句使用单独的表达式:
SELECT
CASE sig.order WHEN 1 THEN emp.last_name END AS Sig_1_Emp,
CASE sig.order WHEN 3 THEN emp.last_name END AS Sig_3_Staff
FROM
VisitSignatures AS sig
JOIN
Employees AS emp ON (...);
请注意,我已将您的表别名化以使语句更清晰;您将填写您的加入条件和所需的任何WHERE
条款。这将使你从以下(加入)表中获得:
+-----------+---------------+
| sig.order | emp.last_name |
+-----------+---------------+
| 1 | 'SMITH' |
| 1 | 'NGUYEN' |
| 3 | 'FIELDS' |
+-----------+---------------+
到此结果集:
+-----------+-------------+
| Sig_1_Emp | Sig_3_Staff |
+-----------+-------------+
| 'SMITH' | NULL |
| 'NGUYEN' | NULL |
| NULL | 'FIELDS' |
+-----------+-------------+
到目前为止,您只完成了第一项任务。对于第二个,您必须使用聚合函数。您使用哪种功能取决于您想要做什么,但如果您想要计算每列中的员工数量,那么您需要做的就是在COUNT()
表达式周围包含CASE
函数。将别名保留在函数之外(并可能将其更改为指示计数的内容)和GROUP BY
查询中请求的任何非聚合列,以获得类似的内容:
SELECT
other_columns,
COUNT(CASE sig.order WHEN 1 THEN emp.last_name END) AS Num_Sig_1,
COUNT(CASE sig.order WHEN 3 THEN emp.last_name END) AS Num_Sig_3
FROM
VisitSignatures AS sig
JOIN
Employees AS emp ON (...)
GROUP BY other_columns;
+-----+-----------+-----------+
| ... | Num_Sig_1 | Num_Sig_3 |
+-----+-----------+-----------+
| ... | 2 | 1 |
+-----+-----------+-----------+
请注意,CASE
表达式为您提供了中间结果集中的字符串 - 如果您只想计算非NULL
值,这可能不是最有效的方法根据您使用的DBMS,进行操作。例如,在MySQL中执行此操作会更有效(为简洁起见,忽略额外的列/表):
SELECT
order = 1 AS Sig_1_Emp,
order = 3 AS Sig_3_Staff
FROM
VisitSignatures;
产:
+-----------+-------------+
| Sig_1_Emp | Sig_3_Staff |
+-----------+-------------+
| 1 | 0 |
| 1 | 0 |
| 0 | 1 |
+-----------+-------------+
您将使用SUM()
代替COUNT()
进行汇总,以获得与之前相同的结果。您还没有说过您正在使用哪个DBMS,但即使它不是MySQL,您也应该仔细考虑是否确实需要在中间结果集中使用这些姓氏。只要表格中没有太多行,但设计效率低下的查询很容易,但在将来会出现问题。
另一方面,您的DBMS可能能够以引用该值的方式优化emp.last_name
而不将其存储在中间表中,并且非常快。这是你必须自己研究的东西。
1 如果您正在使用MySQL,请阅读:Case Expression vs Case Statement
答案 2 :(得分:0)
鉴于您对问题的更新,很明显您缺少的是具有适当聚合函数的GROUP BY
子句。
请注意,在您的示例结果中,前四列(clientvisit_id
,program_id
,visittype
,rev_timein
)在两个示例行中都包含相同的值。如果您GROUP BY
这四列,示例行将被分组为一行,因为它们的值相同。我不确定你为什么不在这里展示non_billable
,但这个概念扩展到你想用来定义不同组的列数。
由于sig_1_emp
和sig_3_staff
列不用于分组,因此它们必须与one of the available aggregate functions一起使用,而不是列列表中的“裸”。在这种情况下,典型的做法是使用MIN()
或MAX()
,这两个行都忽略NULL
行,只返回多个值中的一个。当组中的所有值相等时,它们是等价的,否则它们会给出最小值或最大值。
如果您不自信地知道所有非NULL
行具有相同的值,那么您将必须根据行执行的方式找出选择或派生值的其他方法。 not 出现在GROUP BY
子句中,或者随意取任何值作为最大值或最小值进行比较。请记住,每种数据类型都可能有自己的比较规则。似乎不可取。
因此,请尝试将其添加到查询的末尾:
GROUP BY clientvisit_id, program_id, visittype, rev_timein, non_billable
并将CASE
表达式包装起来:
MAX(CASE WHEN CVSig.ord = 1 THEN Employees.last_name END) AS Sig_1_Emp,
MAX(CASE WHEN CVSig.ord = 3 THEN Employees.last_name END) AS Sig_3_Staff
看看是否有诀窍(记住已经说过的警告)。如果您愿意,可以保留ELSE NULL
,但如果没有任何案例属实,表达式将为NULL
;在这种情况下,我不认为明确是值得的房地产(双关语)。