我有一个这样的表(为清晰起见省略了主键):
events:
itemId eventType
-----------------
100 1
101 1
101 2
102 2
102 2
还有其他事件类型,但我只关心1和2。我想找到eventType
每个itemId
的计数,但我还需要一种方便的方法来对结果进行数学计算。例如,我想要一个这样的输出:
itemId ones twos onesPct twosPct
-------------------------------------
100 1 0 1.0 0.0
101 1 1 0.5 0.5
102 0 2 0.0 1.0
在我的实际应用中,我所执行的数学运算要比百分比复杂得多。方言是T-SQL。所以现在我有这样的查询;我对SQL并不是那么出色,所以我想出的最好的是:
SELECT
COALESCE(onest.itemId,twost.itemId) itemId,
COALESCE(onest.n,0) ones,
COALESCE(twost.n,0) twos,
1.0*COALESCE(onest.n,0) / (COALESCE(onest.n,0) + COALESCE(twost.n,0)) onesPct,
1.0*COALESCE(twost.n,0) / (COALESCE(onest.n,0) + COALESCE(twost.n,0)) twosPct
FROM
(SELECT itemId, COUNT(*) n
FROM events
WHERE eventType = 1
GROUP BY itemId) onest
FULL OUTER JOIN
(SELECT itemId, COUNT(*) n
FROM events
WHERE eventType = 2
GROUP BY itemId) twost
ON onest.itemId = twost.itemId
这是有效的,除了方程中的所有COALESCE
变得非常笨重。所以我有两个问题:
最重要的是:有没有办法在更全局的层面上将NULL从外部联接转换为0,这样我就不必继续写到处都是COALESCE(onest.n,0)
?从我到目前为止看到的情况来看,我不允许在其他列规范中使用列别名,所以我不能简单地做到例如上述查询中的(1.0 * ones / (ones + twos)) onestPct
(除非有办法执行此操作)?
是否有更短的查询可以完成这一切?这看起来像是一堆子查询。
我不太关心性能,主要任务是数据挖掘和分析。
此外,对于糟糕的头衔道歉,我无法提出一个很好的简短摘要。
答案 0 :(得分:3)
我知道你说你所做的事情比百分比更复杂,但我认为无论关键只是一个子查询。
首先进行分组工作。完成后,将其用作查询的源,您可以在其中进行实际数学运算。当然,如果它过于复杂,您可以考虑将该子查询放入临时表中。
所以如果只是你提供的数据,我会这样做。
select itemid,
ones,
twos,
ones + twos as total,
100 * (round(ones / (ones + twos), 4)) as ones_perc,
100 * (round(twos / (ones + twos), 4)) as twos_perc
from
(select itemid,
sum(case when eventtype = 1 then 1 else 0 end) as ones,
sum(case when eventtype = 2 then 1 else 0 end) as twos
from a
group by itemid)b
答案 1 :(得分:1)
您可以在SUM()
上使用汇总函数(CASE
),从而简化整个查询:
select itemId,
sum(case eventType when 1 then 1 else 0 end) ones,
sum(case eventType when 2 then 1 else 0 end) twos,
convert(float, sum(case eventType when 1 then 1 else 0 end)) / count(eventType) onesPct,
convert(float, sum(case eventType when 2 then 1 else 0 end)) / count(eventType) twosPct
from events
group by itemId
如果有些项目没有任何事件,您应该排除它们或单独处理百分比计算,因为上面的查询将导致除以零。
答案 2 :(得分:1)
select itemId,ones,twos,ones/c onesPct,twos/c twosPct from (
select itemId,sum(2-eventType) ones,sum(eventType-1) twos,sum(1.0) c from events where eventType in (1,2) group by itemId
) e