Why Oracle is saying not a GROUP BY expression?

后端 未结 4 1466
不知归路
不知归路 2020-12-21 15:58

I am Trying to retrive data from the Oracle database table with following conditions

  1. All entries found by zip-code should be grouped, sorted by zip-code desce
相关标签:
4条回答
  • 2020-12-21 16:02

    The specific answer to your question is that uuid is not included in the group by expression. Other answers have already explained the MySQL (mis) feature that allows this to happen. Fixing the query is easy:

    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)
    

    I also removed the "distinct" which should be redundant when using group by.

    That said, I don't see how this satisfies your original question. I would expect something more along the lines of the following:

    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
    

    This may not be exactly what you need, but it should point you in the right direction. Also, this is standard SQL and will work in both databases.

    0 讨论(0)
  • 2020-12-21 16:07

    This happens to you just because MySQL breaks the logic of SQL.

    Let's say we have table emp:

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

    and the query:

    select dept, ename
    from emp 
    group by dept;
    

    you'll get what? You should get two lines, because there are two departments, but the query ask for ename. For 20 is clear but for 10 the engine should return what?

    It shoud return an error. Can't guess what ename to give. Oracle shoot an error - your error, but MySQL gets an ename(not guaranteed which). That's missleading and may conduct bugs.

    Correct queries would be:

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

    and

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

    After you correct this part, you'll have to resolve the

    COUNT(*) over() AS rowcount
    

    part. In oracle, AFAIK, you can't mix analytic functions with group by queries.

    0 讨论(0)
  • 2020-12-21 16:11

    I don't know about MySQL, but following works in 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;
    
    0 讨论(0)
  • 2020-12-21 16:24

    It works in MySQl because MySQL has a shoddy interpretation of SQL.

    In any proper dialect, anything in the SELECT or ORDER BY clauses needs to be either an aggregate function, or a GROUPed expression.

    At the very least, you're going to need to group by ba.uuid, lastname and city.

    0 讨论(0)
提交回复
热议问题