组合 3 SELECT 语句输出 1 table
Combining 3 SELECT statements to output 1 table
我有三个查询结果。
查询 1:
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 1 AND workid < 557 AND workid > 188
GROUP BY employeeid, clientid ORDER BY clientid ASC;
employeeid | clientid | under_over_1
------------+----------+--------------
1 | 3 | 0.54
1 | 4 | 0.47
1 | 6 | 0.45
1 | 7 | 0.59
. | . | .
. | . | .
查询 2:
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 2
GROUP BY employeeid, clientid ORDER BY clientid ASC;
employeeid | clientid | under_over_1
------------+----------+--------------
2 | 2 | 1.01
2 | 3 | 0.21
2 | 4 | 0.71
2 | 6 | 0.68
. | . | .
. | . | .
查询:3
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 3
GROUP BY employeeid, clientid ORDER BY clientid ASC;
employeeid | clientid | under_over_1
------------+----------+--------------
3 | 4 | 0.70
3 | 6 | 0.54
3 | 7 | 1.03
3 | 11 | 0.74
. | . | .
. | . | .
我想输出一个 table 和所有三个查询的结果,例如(很抱歉,我必须在这里写更多,这样我才能提交这个 post。我希望这是够了;-)):
employeeid | clientid | under_over_1
------------+----------+--------------
1 | 3 | 0.54
1 | 4 | 0.47
1 | 6 | 0.45
1 | 7 | 0.59
. | . | .
. | . | .
2 | 2 | 1.01
2 | 3 | 0.21
2 | 4 | 0.71
2 | 6 | 0.68
. | . | .
. | . | .
3 | 4 | 0.70
3 | 6 | 0.54
3 | 7 | 1.03
3 | 11 | 0.74
. | . | .
. | . | .
我试过 UNION ALL
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 1 AND workid < 557 AND workid > 188
GROUP BY employeeid, clientid ORDER BY clientid ASC
UNION ALL
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 3
GROUP BY employeeid, clientid ORDER BY clientid ASC
UNION ALL
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 2
GROUP BY employeeid, clientid ORDER BY clientid ASC;
但是,我收到以下错误:
ERROR: syntax error at or near "UNION"
LINE 7: UNION ALL
我不确定为什么这是错误的,或者 UNION ALL
是否是正确的方法。有人知道吗?
删除所有 ORDER BY
。然后使用生成的查询作为派生 table。要保留您可能想要的顺序,您可以使用 CASE
表达式将 employeeid
映射到确定顺序的整数:
SELECT x.employeeid,
x.clientid,
x.under_over_1
FROM (<your UNION ALL query without the ORDER BYs>) x
ORDER BY CASE x.employeeid
WHEN 1 THEN
1
WHEN 2 THEN
3
WHEN 3 THEN
2
END,
x.clientid;
错误的直接原因是引用 the manual:
(ORDER BY
and LIMIT
can be attached to a subexpression if it is
enclosed in parentheses. Without parentheses, these clauses will be
taken to apply to the result of the UNION
, not to its right-hand input
expression.)
大胆强调我的。
因此,正如@wilx 所建议的,将每个 SELECT
括在括号中将修复 that.
但还有更多。
合并为单个查询
SELECT employeeid, work.clientid -- no DISTINCT
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE (employeeid IN (1, 2) OR
employeeid = 3
AND workid < 557
AND workid > 188)
GROUP BY employeeid, clientid
ORDER BY CASE employeeid
WHEN 1 THEN 1
WHEN 2 THEN 3
WHEN 3 THEN 2
END
, clientid;
合并 3 个 SELECT
查询。
删除多余的DISTINCT
。在 GROUP BY
.
之后这是一个昂贵的空操作
不是从开始和结束时间戳等中提取小时和分钟,而是通过简单的减法计算 interval
(与 timestamp
或 time
值类似)并提取epoch
来自它。给你秒数。除以 60,您可以更快地得到分钟数。 79 是 60 * 1.31666666666667 的结果。
manual about extracting epoch
:
For timestamp with time zone
values, the number of seconds since
1970-01-01 00:00:00 UTC (can be negative); for date
and timestamp
values, the number of seconds since 1970-01-01 00:00:00 local time;
for interval
values, the total number of seconds in the interval
大胆强调我的。
由于这删除了 UNION ALL
,因此不再需要顶部提到的括号。
CASE
表达式弥补了 employeeid
中的混合顺序,如 .
如果无法合并查询
如果出于某种原因,您不能或不会合并三个原始 SELECT
查询,请改为执行此操作:
( -- parentheses required
SELECT employeeid, work.clientid -- no DISTINCT !
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 1
AND workid < 557
AND workid > 188
GROUP BY clientid -- no need to GROUP BY employeeid while filtering single value
ORDER BY clientid
)
UNION ALL
(
SELECT employeeid, work.clientid
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 3
GROUP BY clientid
ORDER BY clientid
)
UNION ALL
(
SELECT employeeid, work.clientid
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 2
GROUP BY clientid
ORDER BY clientid
);
-- no outer ORDER BY required
按照 SELECT
保留 ORDER BY
并添加括号以修复语法。 UNION ALL
(与 UNION
相反)只是附加保留单个 SELECT
顺序的结果。这应该比订购整套UNION ALL
更便宜。而且您确实想“按原样”继续使用查询 SELECT
个查询 ...
以上大部分其他建议均适用。
旁白: 养成使用 table 别名和 table 限定所有列的习惯查询加入多个 tables。对以后的更改更加健壮并且更易于阅读/调试。
我有三个查询结果。
查询 1:
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 1 AND workid < 557 AND workid > 188
GROUP BY employeeid, clientid ORDER BY clientid ASC;
employeeid | clientid | under_over_1
------------+----------+--------------
1 | 3 | 0.54
1 | 4 | 0.47
1 | 6 | 0.45
1 | 7 | 0.59
. | . | .
. | . | .
查询 2:
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 2
GROUP BY employeeid, clientid ORDER BY clientid ASC;
employeeid | clientid | under_over_1
------------+----------+--------------
2 | 2 | 1.01
2 | 3 | 0.21
2 | 4 | 0.71
2 | 6 | 0.68
. | . | .
. | . | .
查询:3
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 3
GROUP BY employeeid, clientid ORDER BY clientid ASC;
employeeid | clientid | under_over_1
------------+----------+--------------
3 | 4 | 0.70
3 | 6 | 0.54
3 | 7 | 1.03
3 | 11 | 0.74
. | . | .
. | . | .
我想输出一个 table 和所有三个查询的结果,例如(很抱歉,我必须在这里写更多,这样我才能提交这个 post。我希望这是够了;-)):
employeeid | clientid | under_over_1
------------+----------+--------------
1 | 3 | 0.54
1 | 4 | 0.47
1 | 6 | 0.45
1 | 7 | 0.59
. | . | .
. | . | .
2 | 2 | 1.01
2 | 3 | 0.21
2 | 4 | 0.71
2 | 6 | 0.68
. | . | .
. | . | .
3 | 4 | 0.70
3 | 6 | 0.54
3 | 7 | 1.03
3 | 11 | 0.74
. | . | .
. | . | .
我试过 UNION ALL
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 1 AND workid < 557 AND workid > 188
GROUP BY employeeid, clientid ORDER BY clientid ASC
UNION ALL
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 3
GROUP BY employeeid, clientid ORDER BY clientid ASC
UNION ALL
SELECT DISTINCT employeeid, work.clientid, ROUND ((CAST (AVG(current_lawn_price) AS numeric) / CAST (AVG((((EXTRACT(HOUR FROM job_finish)*60) + EXTRACT(MIN FROM job_finish))) - ((EXTRACT(HOUR FROM job_start)*60) + EXTRACT(MIN FROM job_start))) AS numeric)) / 1.31666666666667, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 2
GROUP BY employeeid, clientid ORDER BY clientid ASC;
但是,我收到以下错误:
ERROR: syntax error at or near "UNION" LINE 7: UNION ALL
我不确定为什么这是错误的,或者 UNION ALL
是否是正确的方法。有人知道吗?
删除所有 ORDER BY
。然后使用生成的查询作为派生 table。要保留您可能想要的顺序,您可以使用 CASE
表达式将 employeeid
映射到确定顺序的整数:
SELECT x.employeeid,
x.clientid,
x.under_over_1
FROM (<your UNION ALL query without the ORDER BYs>) x
ORDER BY CASE x.employeeid
WHEN 1 THEN
1
WHEN 2 THEN
3
WHEN 3 THEN
2
END,
x.clientid;
错误的直接原因是引用 the manual:
(
ORDER BY
andLIMIT
can be attached to a subexpression if it is enclosed in parentheses. Without parentheses, these clauses will be taken to apply to the result of theUNION
, not to its right-hand input expression.)
大胆强调我的。
因此,正如@wilx 所建议的,将每个 SELECT
括在括号中将修复 that.
但还有更多。
合并为单个查询
SELECT employeeid, work.clientid -- no DISTINCT
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE (employeeid IN (1, 2) OR
employeeid = 3
AND workid < 557
AND workid > 188)
GROUP BY employeeid, clientid
ORDER BY CASE employeeid
WHEN 1 THEN 1
WHEN 2 THEN 3
WHEN 3 THEN 2
END
, clientid;
合并 3 个 SELECT
查询。
删除多余的DISTINCT
。在 GROUP BY
.
不是从开始和结束时间戳等中提取小时和分钟,而是通过简单的减法计算 interval
(与 timestamp
或 time
值类似)并提取epoch
来自它。给你秒数。除以 60,您可以更快地得到分钟数。 79 是 60 * 1.31666666666667 的结果。
manual about extracting epoch
:
For
timestamp with time zone
values, the number of seconds since 1970-01-01 00:00:00 UTC (can be negative); fordate
andtimestamp
values, the number of seconds since 1970-01-01 00:00:00 local time; forinterval
values, the total number of seconds in the interval
大胆强调我的。
由于这删除了 UNION ALL
,因此不再需要顶部提到的括号。
CASE
表达式弥补了 employeeid
中的混合顺序,如
如果无法合并查询
如果出于某种原因,您不能或不会合并三个原始 SELECT
查询,请改为执行此操作:
( -- parentheses required
SELECT employeeid, work.clientid -- no DISTINCT !
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 1
AND workid < 557
AND workid > 188
GROUP BY clientid -- no need to GROUP BY employeeid while filtering single value
ORDER BY clientid
)
UNION ALL
(
SELECT employeeid, work.clientid
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 3
GROUP BY clientid
ORDER BY clientid
)
UNION ALL
(
SELECT employeeid, work.clientid
, ROUND ((AVG(current_lawn_price)
/ AVG(extract(epoch FROM job_finish - job_start)))::numeric / 79, 2) AS under_over_1
FROM work
JOIN timesheet USING (date_linkid)
JOIN client USING (clientid)
WHERE employeeid = 2
GROUP BY clientid
ORDER BY clientid
);
-- no outer ORDER BY required
按照 SELECT
保留 ORDER BY
并添加括号以修复语法。 UNION ALL
(与 UNION
相反)只是附加保留单个 SELECT
顺序的结果。这应该比订购整套UNION ALL
更便宜。而且您确实想“按原样”继续使用查询 SELECT
个查询 ...
以上大部分其他建议均适用。
旁白: 养成使用 table 别名和 table 限定所有列的习惯查询加入多个 tables。对以后的更改更加健壮并且更易于阅读/调试。