重写MySQL SQL for Oracle 11g

时间:2015-06-24 07:07:00

标签: php mysql oracle oracle11g

这是原始的MySQL声明:

select transactions.username,
       count(transactions.username) as total_transactions,
       last_device,
       last_transaction
  from transactions
 inner join (select username,
                    terminal     as last_device,
                    request_date as last_transaction
               from transactions t1
              where request_date =
                    (select max(request_date)
                       from transactions t2
                      where t1.username = t2.username)) as transactions_per_user
    on transactions_per_user.username = transactions.username
 group by username;

甲骨文并不喜欢这句话,所以在经过大量的反复试验之后我将其改写为:

 select transactions_per_user.username, 
        count(transactions_per_user.username) as total_transactions, 
        MAX(transactions_per_user.last_transaction) as last_transaction, 
        MAX(transactions_per_user.last_device) as last_device
 from 
 transactions 
 inner join 
 (
    select username, terminal as last_device, request_date as last_transaction 
    from transactions t1 
    where request_date = (select max(request_date) 
    from transactions t2 where t1.username=t2.username)
) 
transactions_per_user on transactions_per_user.username=transactions.username 
group by transactions_per_user.username;

这似乎是对的,但我担心在那里使用MAX。我不太明白为什么会这样。任何人都可以验证它是否可以,如果不帮助我编写一个可以在oracle中保持接近mysql的语句,如果sql将在oracle和mysql中运行,那就更好了。

基本上我正在尝试生成一个按用户分组的表,列出了他们上次的交易日期以及最后使用的设备以及他们所做的交易次数。

1 个答案:

答案 0 :(得分:1)

我使用PL / SQL美化器来格式化相同格式的语句,并使用TortuiseSVN来比较它们。

第一次查询:

SELECT transactions.username,
       COUNT(transactions.username) AS total_transactions,
       last_device,
       last_transaction
  FROM transactions
 INNER JOIN (SELECT username,
                    terminal     AS last_device,
                    request_date AS last_transaction
               FROM transactions t1
              WHERE request_date =
                    (SELECT MAX(request_date)
                       FROM transactions t2
                      WHERE t1.username = t2.username)) AS transactions_per_user
    ON transactions_per_user.username = transactions.username
 GROUP BY username

第二个查询:

SELECT transactions_per_user.username,
       COUNT(transactions_per_user.username) AS total_transactions,
       MAX(transactions_per_user.last_transaction) AS last_transaction,
       MAX(transactions_per_user.last_device) AS last_device
  FROM transactions
 INNER JOIN (SELECT username,
                    terminal     AS last_device,
                    request_date AS last_transaction
               FROM transactions t1
              WHERE request_date =
                    (SELECT MAX(request_date)
                       FROM transactions t2
                      WHERE t1.username = t2.username)) transactions_per_user
    ON transactions_per_user.username = transactions.username
 GROUP BY transactions_per_user.username;

以下是更改:

  1. 事务已更改为第1行和第2行中的transactions_per_user 这很好,因为你内部加入这些数据集 在transactions_per_user.username = transactions.username (但这种改变不是必要的)
  2. last_device,last_transaction已更改为
    MAX(transactions_per_user.last_transaction)AS last_transaction,
    MAX(transactions_per_user.last_device)AS last_device
    在Oracle中,如果列不在组列表中,则不能使用没有分组功能的列(即使它们对于组中的所有行都相同)。 Oracle在获取数据之前检查查询,因此它不知道它将使用哪些数据。 (我不确定这在MySQL中是如何工作的)
    据我所知,这些列在组内是相等的,所以这里的min和max都很好。
  3. 在“AS transactions_per_user”中删除了AS - 这不是必需的(两种语法都可以正常工作)
  4. “GROUP BY username”已更改为“GROUP BY transactions_per_user.username”
    如果您使用“ON”子句加入,则需要明确指定表名或别名,同时提及这些列,如果它们具有相同的名称(否则Oracle不知道您的意思是什么列) 即使你有内部联接,你也应该使用明确的别名 如果您使用“USING”子句加入,则oracle将这两列合并为1,并且您不能使用表别名。
    您可以选择自己喜欢的语法。