2

我正在尝试使用以下条件从 Oracle 数据库表中检索数据

  1. 所有按邮政编码找到的条目都应分组,按邮政编码降序排序。
  2. 按城市找到的条目应按字母顺序分组。
  3. 按经销商名称找到的所有条目都应按字母顺序进行分组和排序。

为了满足上述条件,我编写了如下查询

SELECT DISTINCT ba.uuid AS uuid
        , COUNT(*) over() AS rowcount 
FROM basicaddress ba 
WHERE ba.postalcode='143456' 
OR ba.lastname LIKE '%143456%' 
OR ba.city LIKE '%143456%'
GROUP BY
    CASE WHEN ba.postalcode='143456' THEN ba.postalcode END 
ORDER BY 
    CASE WHEN ba.postalcode='143456' THEN ba.postalcode END DESC, 
    CASE WHEN ba.lastname LIKE '%143456%' THEN ba.lastname END ASC, 
    CASE WHEN ba.city LIKE '%143456%' THEN ba.city ELSE ba.postalcode END DESC

此查询在 MYSQL 中运行良好,但在 oracle 中显示“不是 GROUP BY 表达式”

任何帮助将不胜感激

4

4 回答 4

1

这发生在你身上只是因为 MySQL 破坏了 SQL 的逻辑。

假设我们有表emp:

id ename dept
1  mark  10
2  John  10
3  Mary  10
4  Jane  20

和查询:

select dept, ename
from emp 
group by dept;

你会得到什么?你应该得到两行,因为有两个部门,但查询要求输入姓名。对于 20 是明确的,但对于 10,引擎应该返回什么?

它应该返回一个错误。猜不出要给什么名字。甲骨文报错 - 你的错误,但 MySQL 得到一个 ename(不保证哪个)。这是误导性的,可能会产生错误。

正确的查询是:

select dept, max(ename) --the latest, alaphabeticaly
from emp 
group by dept;

--all enames and groups
select dept, ename 
from emp 
group by dept, ename;

更正此部分后,您必须解决

COUNT(*) over() AS rowcount

部分。在 oracle、AFAIK 中,您不能将分析函数与分组查询混合使用。

于 2012-09-24T12:58:45.123 回答
1

您问题的具体答案uuid是不包含在按表达式分组中。其他答案已经解释了允许这种情况发生的 MySQL (mis) 功能。修复查询很容易:

SELECT ba.uuid AS uuid, COUNT(*) over() AS rowcount
FROM basicaddress ba 
WHERE ba.postalcode='143456' OR ba.lastname LIKE '%143456%' OR ba.city LIKE '%143456%'
GROUP BY uuid,
        CASE WHEN ba.postalcode='143456' THEN ba.postalcode END 
ORDER BY 
        max(CASE WHEN ba.postalcode='143456' THEN ba.postalcode END) DESC, 
        max(CASE WHEN ba.lastname LIKE '%143456%' THEN ba.lastname END) ASC, 
        max(CASE WHEN ba.city LIKE '%143456%' THEN ba.city ELSE ba.postalcode END)

我还删除了在使用 group by 时应该是多余的“distinct”。

也就是说,我不明白这如何满足您最初的问题。我期待更多类似以下内容:

select (case when postalcode is not null then postalcode
             when city is not null then city
             when lastname is not null then lastname
        end),
       (case when postalcode is not null then 1
             when city is not null then 2
             when lastname is not null then 3
        end),
       count(*)
from basicaddress ba
group by (case when postalcode is not null then postalcode
               when city is not null then city
               when lastname is not null then lastname
          end),
         (case when postalcode is not null then 1
             when city is not null then 2
             when lastname is not null then 3
        end)
order by 1, 2

这可能不是您所需要的,但它应该为您指明正确的方向。此外,这是标准 SQL,适用于两个数据库。

于 2012-09-24T13:28:00.210 回答
0

它在 MySQl 中有效,因为 MySQL 对 SQL 的解释很拙劣。

在任何适当的方言中,SELECTorORDER BY子句中的任何内容都需要是聚合函数或 GROUPed 表达式。

至少,您需要按 ba.uuid、姓氏和城市进行分组。

于 2012-09-24T12:32:37.463 回答
0

我不了解 MySQL,但以下在 Oracle 11g 中有效:

With 
T_PATTERN as (select '%143456%' as PATTERN from DUAL)
, T_INPUT as (
  select 1 as UUID, 'X143456y' as FIRSTNAME, 'last1' as LASTNAME, 'u143456v' as CITY, 'w143456z' as POSTALCODE from DUAL union
  select 2 as UUID, 'first2' as FIRSTNAME, 'a143456b' as LASTNAME, 'a143456b' as CITY, 'postal2' as POSTALCODE from DUAL union
  select 3 as UUID, 'first3' as FIRSTNAME, 'last3' as LASTNAME, 'c143456d' as CITY, 'postal3' as POSTALCODE from DUAL union
  select 4 as UUID, 'first4' as FIRSTNAME, 'last4' as LASTNAME, 'city4' as CITY, 'postal4' as POSTALCODE from DUAL
),
Q_FNAME as (
  select TI.UUID, TI.FIRSTNAME, COUNT(*) FN_COUNT from T_INPUT TI inner join T_PATTERN TP on 1=1 
  where UPPER(TI.FIRSTNAME) like TP.PATTERN
  GROUP BY TI.UUID, TI.FIRSTNAME
),
Q_LNAME as (
  select TI.UUID, TI.LASTNAME, COUNT(*) LN_COUNT from T_INPUT TI inner join T_PATTERN TP on 1=1 
  where UPPER(TI.LASTNAME) like TP.PATTERN
  group by TI.UUID, TI.LASTNAME
),
Q_CITY as (
  select TI.UUID, TI.CITY, COUNT(*) CT_COUNT from T_INPUT TI inner join T_PATTERN TP on 1=1 
  where UPPER(TI.CITY) like TP.PATTERN
  group by TI.UUID, TI.CITY
),
Q_PCODE as (
  select TI.UUID, TI.POSTALCODE, COUNT(*) PC_COUNT from T_INPUT TI inner join T_PATTERN TP on 1=1 
  where UPPER(TI.POSTALCODE) like TP.PATTERN
  group by TI.UUID, TI.POSTALCODE
)
select TI.UUID, TI.FIRSTNAME, TI.LASTNAME, TI.CITY, TI.POSTALCODE, 
  QF.FN_COUNT, QL.LN_COUNT, QC.CT_COUNT, QP.PC_COUNT
from T_INPUT ti
left join Q_FNAME QF on TI.UUID=QF.UUID
left join Q_LNAME QL on TI.UUID=QL.UUID
left join Q_CITY QC on TI.UUID=QC.UUID
left join Q_PCODE QP on TI.UUID=QP.UUID
order by ti.UUID;
于 2012-11-06T13:29:33.167 回答