4

我有一个适用于 MySQL 但不适用于 Oracle 的查询,我正在尝试转换。这是我的桌子:

unique_row_id  http_session_id  page_name   page_hit_timestamp
----------------------------------------------------------------
0              123456789        index.html  2010-01-20 15:00:00
1              123456789        info.html   2010-01-20 15:00:05
2              123456789        faq.html    2010-01-20 15:00:15
3              987654321        index.html  2010-01-20 16:00:00
4              987654321        faq.html    2010-01-20 16:00:05
5              987654321        info.html   2010-01-20 16:00:15
6              111111111        index.html  2010-01-20 16:01:00
7              111111111        faq.html    2010-01-20 16:01:05
8              111111111        info.html   2010-01-20 16:01:15

SQL是

select http_session_id, unique_row_id, page_name, page_hit_timestamp 
from page_hits 
group by http_session_id;

在 MySQL 上,这将返回 3 行(每个唯一的 http_session_id 一个)。

在 Oracle 上,我收到“ORA-00979:不是 GROUP BY 表达式”错误。我也尝试过使用 distinct ,但我无法让它工作。

为了清楚起见 - 我想要一个每个唯一 http_session_id 包含一行的 ResultSet。最好 unique_row_id 是最大值(例如 http_session_id==123456789 为 2),但这并不重要。

我即将将其分解为多个单独的 sql 语句(一个“选择不同的 http_session_id”,另一个迭代所有这些并选择 max(unique_row_id)。任何指针都将不胜感激 - 我很想避免这!

Rgds,凯文。

4

5 回答 5

10

您遇到 ORA 错误的原因是因为 MySQL 支持非标准的 GROUP BY 子句,称其为“功能”。它记录在这里

标准 SQL GROUP BY 子句必须包括SELECT 子句中指定的所有列,这些列未包含在聚合函数(LIKE COUNT、MAX/MIN 等)中,以在 GROUP BY 子句中指定。

如果您希望每个 http_session_id 值有一个唯一的行 - 请查看使用 ROW_NUMBER:

SELECT x.*
  FROM (select http_session_id, unique_row_id, page_name, page_hit_timestamp,
               ROW_NUMBER() OVER (PARTITION BY http_session_id 
                                      ORDER BY http_session_id) AS rank
          FROM page_hits) x
 WHERE x.rank = 1
于 2010-07-06T22:17:35.520 回答
2

这会起作用吗:

select max(unique_row_id), http_session_id
from page_hits
group by http_session_id

顺便说一句;我的 sql 在结果集中为包含在结果集中但不在 group by 子句中的列返回什么?(page_name, page_hit_timestamp)

于 2010-07-06T22:17:31.740 回答
0

我认为 GROUP BY 需要在 SQL 标准中的 WHERE 子句或聚合函数中使用变量?

尝试使用SELECT MAX(unique_row_id) GROUP BY http_session_id.

于 2010-07-06T22:14:35.830 回答
0

在标准 SQL 中,如果您有 GROUP BY 子句,则所有不属于它的列都必须在聚合中。在 MySQL 中,这个规则被设计放宽了。

例如,这在 MySQL 中是允许的,但在标准 SQL 中是不允许的:

SELECT customer_id, country, SUM(amount) FROM records GROUP BY customer_id

有一个警告:MySQL 假设您知道自己在做什么。如果同一客户在多个国家/地区有记录,则查询将仅获取表中的第一个国家/地区,而忽略所有其他国家/地区。此外,由于行的顺序是未定义的,并且没有 ORDER BY,因此每次运行查询时可能会得到不同的结果。

在标准 SQL 中,您有两种选择:

SELECT customer_id, country, SUM(amount) FROM records GROUP BY customer_id, country

或者

SELECT customer_id, MIN(country), SUM(amount) FROM records GROUP BY customer_id
于 2010-07-06T22:42:38.300 回答
0

如果需要,Oracle 中的另一个选项:

select DISTINCT
       FIRST_VALUE(unique_row_id)
       OVER (PARTITION BY http_session_id
             ORDER BY unique_row_id DESC) unique_row_id,
       http_session_id,
       FIRST_VALUE(page_name)
       OVER (PARTITION BY http_session_id
             ORDER BY unique_row_id DESC) page_name,
       FIRST_VALUE(page_hit_timestamp)
       OVER (PARTITION BY http_session_id
             ORDER BY unique_row_id DESC) page_hit_timestamp
from page_hits;

这将获得一组不同的http_session_id's,并且对于每个,返回unique_row_id,page_namepage_hit_timestamp从具有最大的行中unique_row_id返回http_session_id,例如:

unique_row_id  http_session_id  page_name   page_hit_timestamp
----------------------------------------------------------------
2              123456789        faq.html    2010-01-20 15:00:15
5              987654321        info.html   2010-01-20 16:00:15
8              111111111        info.html   2010-01-20 16:01:15
于 2010-07-07T01:16:37.400 回答