简体   繁体   English

为Oracle 11g重写MySQL SQL

[英]rewrite MySQL SQL for Oracle 11g

Here is the original MySQL statement: 这是原始的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;

Oracle didn't like this statement, so after a lot of trial and error I rewrote it to this: Oracle不喜欢此声明,因此经过反复试验,我将其重写为:

 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;

It seems to the right thing but I am concerned about using MAX there. 看起来似乎正确,但我担心在那里使用MAX。 I can't quite understand why it works. 我不太明白为什么会这样。 Can anyone verify it is ok if not help me write a statement that will work in oracle keeping close to the mysql, even better if the sql will run in both oracle and mysql. 任何人都可以验证它是否可以,如果不能帮我编写一条语句,该语句将在oracle中与mysql保持联系,即使sql可以在oracle和mysql中都运行,甚至更好。

Basically I am trying to generate a table grouped by users that lists their last transaction date and also the last device used and also a count of transactions they have made. 基本上,我试图生成一个按用户分组的表,该表列出了他们的上次交易日期,使用的上次设备以及完成的交易次数。

I used PL/SQL beautifier to format statements with the same format, and TortuiseSVN dif to compare them. 我使用PL / SQL美化器来格式化具有相同格式的语句,并使用TortuiseSVN dif对其进行比较。

first query: 第一个查询:

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

second query: 第二个查询:

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;

Here are changes: 以下是更改:

  1. transactions was changed to transactions_per_user in row 1 and 2 this is fine because you inner join these data sets on transactions_per_user.username = transactions.username (but this change is not necessary) 将事务在第1行和第2行中更改为transactions_per_user,这很好,因为您内部将这些数据集连接在transactions_per_user.username = transaction.username上(但此更改不是必需的)
  2. last_device, last_transaction was changed with last_device,last_transaction已更改为
    MAX(transactions_per_user.last_transaction) AS last_transaction, MAX(transactions_per_user.last_transaction)AS last_transaction,
    MAX(transactions_per_user.last_device) AS last_device MAX(transactions_per_user.last_device)AS last_device
    In Oracle you can't use columns without grouping functions if they are not in group list (even if they are equal for all rows in group). 在Oracle中,如果列不在组列表中,则不能使用没有分组功能的列(即使它们对于组中的所有行都相等)。
    Oracle check query before fetching data, so it doesn't know what data it will work with. Oracle在获取数据之前检查查询,因此它不知道它将使用什么数据。 (I'm not sure how this works in MySQL) (我不确定这在MySQL中如何工作)
    As I understand, these columns are equal within group, so min and max is fine here. 据我了解,这些列在组内相等,因此min和max很好。
  3. AS was deleted in "AS transactions_per_user" - this is not necessary (both syntax works fine) 在“ AS transaction_per_user”中删除了AS-不必要(两种语法都可以正常工作)
  4. "GROUP BY username" was changed with "GROUP BY transactions_per_user.username" “ GROUP BY用户名”已更改为“ GROUP BY transaction_per_user.username”
    If you join with "ON" clause you need to explicitly specify table name or alias while mentioning these columns if they have equal names (otherwise Oracle doesn't know what column do you mean) 如果使用“ ON”子句进行连接,则在提及这些具有相同名称的列时,需要显式指定表名称或别名(否则,Oracle不知道您的意思是哪一列)
    Even if you have inner join you should use explicit alias. 即使您具有内部联接,也应使用显式别名。
    If you join with "USING" clause, then oracle merge these 2 columns into 1, and you can't use table alias for it. 如果使用“ USING”子句进行连接,则oracle将这2列合并为1,并且不能为其使用表别名。
    You may choose either syntax you like. 您可以选择任意一种语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM