sql - 计算时间戳列的相等日期部分跨所述列的组
问题描述
我想计算重复的日期值。我已经知道我的字段“WHEN”是一个时间戳,所以我必须将它转换为日期类型。
我的实际查询如下所示:
SELECT
u.USERNAME,
r."WHEN",
r.UPDATEINOUT,
case (r.UPDATEINOUT) when 0 then 0 when 1 then 1 else r.INOUT end INOUT
FROM
ATTENDANT r
LEFT JOIN
USERS u ON r.USERID = u.ID
where
u.USERNAME = 'rk' and (r.UPDATEINOUT = 1 or r.UPDATEINOUT = 0 or r.UPDATEINOUT is null)
group by
r."WHEN",
INOUT,
u.USERNAME,
r.UPDATEINOUT
order by
r."WHEN"
这是结果:
Username WHEN UPDATEINOUT INOUT
rk 09.04.2018, 14:59:45.000 [null] 0
rk 09.04.2018, 14:59:51.000 [null] 1
rk 11.04.2018, 08:31:02.000 [null] 0
rk 11.04.2018, 12:06:52.000 [null] 1
rk 11.04.2018, 12:10:29.000 [null] 0
rk 11.04.2018, 12:23:09.000 [null] 1
rk 11.04.2018, 12:43:47.000 [null] 0
rk 11.04.2018, 17:07:40.000 [null] 1
现在我想计算重复的日期,结果应该是这样的:
Username WHEN UPDATEINOUT INOUT Count
rk 09.04.2018, 14:59:45.000 [null] 0 2
rk 09.04.2018, 14:59:51.000 [null] 1 2
rk 11.04.2018, 08:31:02.000 [null] 0 6
rk 11.04.2018, 12:06:52.000 [null] 1 6
rk 11.04.2018, 12:10:29.000 [null] 0 6
rk 11.04.2018, 12:23:09.000 [null] 1 6
rk 11.04.2018, 12:43:47.000 [null] 0 6
rk 11.04.2018, 17:07:40.000 [null] 1 6
当我添加
count(cast(r."WHEN" as date))
然后它只显示一个。
解决方案
似乎有一些答案建议“做什么”,但没有试图解释为什么结果会像现在这样。怎么了。似乎给主题启动器的是一条鱼,而不是一根钓鱼竿。
当我添加时
count(cast(r."WHEN" as date))
,它只显示一个。
这有点好笑。这条线显示了像英语这样的自然人类语言和像 SQL 这样的数学集合语言之间的新手误解。
R.Kut 将他添加的这一行读作“我想count
知道有多少 [distinct] 值given expression
”。
但这并不是该命令在 SQL 中的实际含义。在 SQL 中,它的意思是“我想count
知道有多少行,其中given expression
不为空”。
count(cast(r."WHEN" as date))
因此, and之间实际上没有区别count(r."WHEN")
- 这两个参数表达式是 bothNULL
或 both NOT NULL
。因此count
,那些同样可以为空的参数的值也是相等的。
试图截断聚合函数的参数值,就像它可以改变可空性一样,是一种误解。我也在那里。需要时间来了解数学集合上的聚合的真正含义,以及在阅读 SQL 时不会阅读英语。
坦率地说,您不仅可以在count (1)
这里删除类型转换,还可以删除列本身 - 它仍然是相同的,因为这些是行,而不是被要求计算的值。除非有行在哪里"WHEN" IS NULL
- 将由group by
但不由count
. 在您阅读并思考完下一部分之后,回来玩弄http://sqlfiddle.com/#!9/ee09a/7
count
现在,我在上面提到的函数还有另一个参数。就是那个“不同”的参数。
备注:有人可能会说distinct
是 SQL 语言的关键字,不是函数的参数,而是事实上的,而不是法律上的,它改变了函数的工作方式,所以在我看来它是参数,以那种不寻常的 SQLish 方式参数通常被赋予函数。或者,另一种推理方式,它可能是函数名称的一部分,如果想象有两个函数可供选择,count
和count-distinct
。
因此,可以count(distinct cast(r."WHEN" as date))
改为添加主题启动器,并且...
....看到没有任何改变。因为虽然这一次他真的会对服务器说用非空(总是只非空!)和distinct
值来计算行 - 计数在组内。
这些群体是什么?
group by
r."WHEN",
INOUT,
u.USERNAME,
r.UPDATEINOUT
看,在各个组中,我们有具有不同时间和日期值“WHEN”的行。还有其他专栏,但我不关注它们。这里的问题是,在每个组中,“WHEN”的时间和日期部分都保持不变。而“相同”的意思是“有一个distinct
值,一次又一次地重复”。如果只有一个distinct
time-and-date 值,那么 only-time 或 only-date 的减少值将具有相同的计数(减少一个值只能使以前不同的值相等,但不能使以前相等的值现在不同)。
当然,在其他情况下,当计数超过未包含在组中的列时(或者根本没有group by
子句时),结果可能会有所不同。count(distinct ...)
可能会做主题启动者期望它做的事情。
http://sqlfiddle.com/#!9/0d65bf/7 - 示例。
但是,必须牢记:
- 这是以服务器完成的额外排序和分组工作为代价的,可能会使查询变慢或消耗大量内存
- 它仍然可以在组内工作(然后组将开始包含
count
ed 列的不同值)。 - ....有时组是整个查询结果集(最简单的变体 - 整个表),如果程序员没有通过添加
group by
子句将其设置为不同:-D
上面链接的示例代码:
create table X(a integer, b integer);
insert into X values (1,1);
insert into X values (1,2);
insert into X values (1,2);
commit;
select count(distinct b) from x group by a
-- Result: 1 row: 2
-- or if the whole table is the group
select count(distinct b) from x
-- Result: 1 row: 2
-- but if the group includes the counted column
-- then every group would contain EXACTLY ONE
-- row with a not-null distinct value
select count(distinct b) from x group by b
-- Result: 2 rows: 1 and 1
在这里,我们对 toy with 进行了另一种修改。
group by
cast(r."WHEN" as date), -- <====
INOUT,
u.USERNAME,
r.UPDATEINOUT
现在,这一次我们告诉服务器组装组,其中“WHEN”中只有“日期”部分相同,而“时间”部分可能不同。
然而....
- 我认为并非每个 SQL 服务器都支持
group by
子句中的表达式。 - 除非有一个
index
完全由该表达式创建的,否则服务器将不得不做很多额外的工作,可能会求助于自然扫描和临时文件分组,这会使查询变得繁重和缓慢。 - 当然,您必须相应地修改列列表。
.
SELECT
u.USERNAME,
cast(r."WHEN" as date), -- <=== no more raw r."WHEN"
r.UPDATEINOUT,
WHEN
因为,好吧,如果您明确要求服务器对它的不同值进行分组,那么您就不能在行中拥有“一个真实值” 。
在这里,您可能会得出结论,没有简单直接的方法来同时拥有组和跨组聚合。或者换一种说法,在一个查询中有两组不同的集合group by
(我不想在UNION
这里提及,mkay?)。
您将需要一组group by
标准来计算具有相同日期部分(但可能时间部分不同)的行,而另一group by
组标准则用于选择和呈现因日期和时间而不同的组。
在简单明了的 SQL 1999 中,这意味着您必须制作 TWOselect
才能以一种或另一种方式进行两个分组,而 Yogesh 和 Gordon 的答案就在这里。
就像 Gordon 在 99 后 SQL 中提到的那样,出现了 Window Functions,它可以让您将这些标准集合二为一select
,但无论如何它们在 Firebird 2.x 中都不可用。
推荐阅读
- reactjs - 如何将 className 传递给`h${headingLevel}` 自定义标签
- c# - Thread 中的 join() 方法实际上在做什么?
- react-native - 有没有办法“淡入”平面列表中的项目?
- ldap - 错误 [LDAP:错误代码 65 - 属性“calFBURL”不允许]
- vba - 运行时错误“70”:权限仅在 Word VBA 中被拒绝
- javascript - 使用 javascript 在 web 上显示特定的 facebook 事件页面
- delphi - TIdSMTP 和 TIdAttachmentMemory - 垃圾邮件过滤器拒绝电子邮件
- reactjs - 在兄弟组件中调用函数
- r - 如何在 R 中使用排他二进制变量来估算数据?
- javascript - 如何迭代模式的属性类型