SQL 使用计数,在同一单元格中多次使用相同的 "Like"
SQL using Count, with same "Like" multiple times in same cell
我想统计 BNxxxx 在评论单元格中被评论了多少次。到目前为止,我可以让每个单元格都被计数一次,但是在一个包含 BNxxxx 的单元格中可能会有多个注释。
例如,这个:
-------
BN0012
-------
BN0012
-------
BN0012
BN0123
-------
应该显示 BN0012 输出 3 次和 BN0123 一次。相反,我只得到了 3 次 BN0012。
这是我的代码:
select COMMENTS, count(*) as TOTAL
from NOTE
Where COMMENTS like '%BN%' AND CREATE_DATE between '01/1/2015' AND '11/03/2015'
group by COMMENTS
order by Total desc;
有什么想法吗?
编辑
我的代码现在看起来像
select BRIDGE_NO, count(*)
from IACD_ASSET b join
IACD_NOTE c
on c.COMMENTS like concat(concat('BN',b.BRIDGE_NO),'%')
Where c.CREATE_DATE between '01/1/2015' AND '11/03/2015' AND length(b.BRIDGE_NO) > 1
group by b.BRIDGE_NO
order by count(*);
问题在于 BN44 与 BN4455 相同.. 尝试过 concat(concat('BN',b.BRIDGE_NO),'_') 结果一无所获,我有什么想法可以得到完全喜欢
你有问题。让我假设你有一个你关心的所有已知 BN 值的 table。然后你可以这样做:
select bn.fullbn, count(*)
from tableBN bn join
comments c
on c.comment like ('%' || bn.fullbn || '%')
group by bn.fullbn;
这个的性能可能会很慢。
如果您碰巧在评论字段中存储了事物列表,那么这是一个非常糟糕的主意。您不应该将列表存储在字符串中;你应该使用路口 table.
尝试在 select 语句中使用 distinct 关键字,为评论引入唯一值。像这样:
select distinct COMMENTS, count(*) as TOTAL
from NOTE
Where COMMENTS like '%BN%' AND CREATE_DATE between '01/1/2015' AND
'11/03/2015'
group by COMMENTS
order by Total desc;
我假设你的 COMMENTS
table 有一个主键列(比如 comment_id
)或者至少 comments
不是CLOB
。如果它是 CLOB
,那么您将无法在该列上使用 GROUP BY
。
您甚至无需查找 table 的 BN....
值即可完成此操作。不保证性能:
WITH d1 AS (
SELECT 1 AS comment_id, 'BN0123 is a terrible thing BN0121 also BN0000' AS comments
, date'2015-01-03' AS create_date
FROM dual
UNION ALL
SELECT 2 AS comment_id, 'BN0125 is a terrible thing BN0120 also BN1000' AS comments
, date'2015-02-03' AS create_date
FROM dual
)
SELECT comment_id, comments, COUNT(*) AS total FROM (
SELECT comment_id, comments, TRIM(REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i')) AS bn
FROM d1
WHERE create_date >= date'2015-01-01'
AND create_date < date'2015-11-04'
CONNECT BY REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i') IS NOT NULL
AND PRIOR comment_id = comment_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
) GROUP BY comment_id, comments;
请注意,我更正了您的过滤器:
CREATE_DATE between '01/1/2015' AND '11/03/2015'
首先,您应该使用 ANSI 日期文字(例如 date'2015-01-01'
);其次,对日期使用 BETWEEN
通常不是一个好主意,因为 Oracle DATE
值包含时间部分。所以这应该改写为:
create_date >= date'2015-01-01'
AND create_date < date'2015-11-04'
请注意,较晚的日期是 11 月 4,以确保我们收集到所有可能在 11 月 3 发表的评论。
如果你想在不聚合计数的情况下查看匹配的评论,请执行以下操作(基本上去掉外部查询):
WITH d1 AS (
SELECT 1 AS comment_id, 'BN0123 is a terrible thing BN0121 also BN0000' AS comments
, date'2015-01-03' AS create_date
FROM dual
UNION ALL
SELECT 2 AS comment_id, 'BN0125 is a terrible thing BN0120 also BN1000' AS comments
, date'2015-02-03' AS create_date
FROM dual
)
SELECT comment_id, comments, TRIM(REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i')) AS bn
FROM d1
WHERE create_date >= date'2015-01-01'
AND create_date < date'2015-11-04'
CONNECT BY REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i') IS NOT NULL
AND PRIOR comment_id = comment_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
鉴于对您的问题的编辑,我认为您需要如下内容:
SELECT b.bridge_no, COUNT(*) AS comment_cnt
FROM iacd_asset b INNER JOIN iacd_note c
ON REGEXP_LIKE(c.comments, '(^|\W)BN' || b.bridge_no || '(\W|$)', 'i')
WHERE c.create_dt >= date'2015-01-01'
AND c.create_dt < date'2015-03-12' -- It just struck me that your dates are dd/mm/yyyy
AND length(b.bridge_no) > 1
GROUP BY b.bridge_no
ORDER BY comment_cnt;
请注意,我在上面的正则表达式中使用 \W
而不是我之前使用的 \s
以确保它捕获诸如 BN1234/BN6547
.
之类的内容
我想统计 BNxxxx 在评论单元格中被评论了多少次。到目前为止,我可以让每个单元格都被计数一次,但是在一个包含 BNxxxx 的单元格中可能会有多个注释。
例如,这个:
-------
BN0012
-------
BN0012
-------
BN0012
BN0123
-------
应该显示 BN0012 输出 3 次和 BN0123 一次。相反,我只得到了 3 次 BN0012。
这是我的代码:
select COMMENTS, count(*) as TOTAL
from NOTE
Where COMMENTS like '%BN%' AND CREATE_DATE between '01/1/2015' AND '11/03/2015'
group by COMMENTS
order by Total desc;
有什么想法吗?
编辑
我的代码现在看起来像
select BRIDGE_NO, count(*)
from IACD_ASSET b join
IACD_NOTE c
on c.COMMENTS like concat(concat('BN',b.BRIDGE_NO),'%')
Where c.CREATE_DATE between '01/1/2015' AND '11/03/2015' AND length(b.BRIDGE_NO) > 1
group by b.BRIDGE_NO
order by count(*);
问题在于 BN44 与 BN4455 相同.. 尝试过 concat(concat('BN',b.BRIDGE_NO),'_') 结果一无所获,我有什么想法可以得到完全喜欢
你有问题。让我假设你有一个你关心的所有已知 BN 值的 table。然后你可以这样做:
select bn.fullbn, count(*)
from tableBN bn join
comments c
on c.comment like ('%' || bn.fullbn || '%')
group by bn.fullbn;
这个的性能可能会很慢。
如果您碰巧在评论字段中存储了事物列表,那么这是一个非常糟糕的主意。您不应该将列表存储在字符串中;你应该使用路口 table.
尝试在 select 语句中使用 distinct 关键字,为评论引入唯一值。像这样:
select distinct COMMENTS, count(*) as TOTAL
from NOTE
Where COMMENTS like '%BN%' AND CREATE_DATE between '01/1/2015' AND
'11/03/2015'
group by COMMENTS
order by Total desc;
我假设你的 COMMENTS
table 有一个主键列(比如 comment_id
)或者至少 comments
不是CLOB
。如果它是 CLOB
,那么您将无法在该列上使用 GROUP BY
。
您甚至无需查找 table 的 BN....
值即可完成此操作。不保证性能:
WITH d1 AS (
SELECT 1 AS comment_id, 'BN0123 is a terrible thing BN0121 also BN0000' AS comments
, date'2015-01-03' AS create_date
FROM dual
UNION ALL
SELECT 2 AS comment_id, 'BN0125 is a terrible thing BN0120 also BN1000' AS comments
, date'2015-02-03' AS create_date
FROM dual
)
SELECT comment_id, comments, COUNT(*) AS total FROM (
SELECT comment_id, comments, TRIM(REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i')) AS bn
FROM d1
WHERE create_date >= date'2015-01-01'
AND create_date < date'2015-11-04'
CONNECT BY REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i') IS NOT NULL
AND PRIOR comment_id = comment_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
) GROUP BY comment_id, comments;
请注意,我更正了您的过滤器:
CREATE_DATE between '01/1/2015' AND '11/03/2015'
首先,您应该使用 ANSI 日期文字(例如 date'2015-01-01'
);其次,对日期使用 BETWEEN
通常不是一个好主意,因为 Oracle DATE
值包含时间部分。所以这应该改写为:
create_date >= date'2015-01-01'
AND create_date < date'2015-11-04'
请注意,较晚的日期是 11 月 4,以确保我们收集到所有可能在 11 月 3 发表的评论。
如果你想在不聚合计数的情况下查看匹配的评论,请执行以下操作(基本上去掉外部查询):
WITH d1 AS (
SELECT 1 AS comment_id, 'BN0123 is a terrible thing BN0121 also BN0000' AS comments
, date'2015-01-03' AS create_date
FROM dual
UNION ALL
SELECT 2 AS comment_id, 'BN0125 is a terrible thing BN0120 also BN1000' AS comments
, date'2015-02-03' AS create_date
FROM dual
)
SELECT comment_id, comments, TRIM(REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i')) AS bn
FROM d1
WHERE create_date >= date'2015-01-01'
AND create_date < date'2015-11-04'
CONNECT BY REGEXP_SUBSTR(comments, '(^|\s)BN\d+(\s|$)', 1, LEVEL, 'i') IS NOT NULL
AND PRIOR comment_id = comment_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
鉴于对您的问题的编辑,我认为您需要如下内容:
SELECT b.bridge_no, COUNT(*) AS comment_cnt
FROM iacd_asset b INNER JOIN iacd_note c
ON REGEXP_LIKE(c.comments, '(^|\W)BN' || b.bridge_no || '(\W|$)', 'i')
WHERE c.create_dt >= date'2015-01-01'
AND c.create_dt < date'2015-03-12' -- It just struck me that your dates are dd/mm/yyyy
AND length(b.bridge_no) > 1
GROUP BY b.bridge_no
ORDER BY comment_cnt;
请注意,我在上面的正则表达式中使用 \W
而不是我之前使用的 \s
以确保它捕获诸如 BN1234/BN6547
.